require(tidyverse)
require(cowplot)
require(broom)
set.seed(12345)

Introduction

Goal

Plotting ASR data for Fig. 1, S1, …

Data

A large set of data were collected and organized by JY and HB into two files, as shown below. Later, we will import more recent datasets. The data formats are not the most consistent. However, we have tried to annotate the headers so as to make the output understandable.

Read in data

tmp <- read_tsv("../input/20220726-ASR-CFU-raw.tsv", col_types = cols(), comment = "#")
raw <- read_csv("../input/20221224-ASR-CFU-raw.csv", col_types = cols(), comment = "#") %>% 
  mutate(Date = gsub("d(\\d\\d)(\\d\\d)(\\d\\d)", "\\1/\\2/\\3", Date),
         Len_1 = recode(Len_1, `2hr` = "2 hr", `45min` = "45 min"),
         Len_2 = recode(Len_2, `2hr` = "2 hr")) %>% 
  select(-`MO/MM`, -`PO/PM`) %>% 
  bind_rows(add_column(tmp, Experimenter = "JL"))

# data sanity check, quick view
sapply(select(raw, Species, Strain, Genotype, Len_1, Len_2, H2O2), unique)
$Species
[1] "Cg" "Sc" "Kl"

$Strain
 [1] "yH001" "yH154" "yH181" "yH149" "yH002" "yH609" "yH610" "yH271" "yH272"
[10] "yH273" "yH262" "yH275"

$Genotype
[1] "wt"         "rim15Δ"     "cta1Δ"      "msn2Δ"      "msn4Δ"     
[6] "msn2Δmsn4Δ"

$Len_1
[1] "45 min"  "2hr"     "90 min"  "135 min"

$Len_2
[1] "2 hr"  "0 min"

$H2O2
 [1] "Mock"   "20mM"   "40mM"   "60mM"   "80mM"   "100mM"  "2mM"    "4mM"   
 [9] "6mM"    "8mM"    "10mM"   "15mM"   "25mM"   "30mM"   "35mM"   "1.5mM" 
[17] "2.5mM"  "3mM"    "3.5mM"  "0.5mM"  "1mM"    "0.2mM"  "0.3mM"  "0.4mM" 
[25] "0.26mM" "0.34mM" "0 mM"   "20 mM"  "40 mM"  "60 mM"  "80 mM"  "100 mM"
[33] "2.2 mM" "2.5 mM" "2 mM"   "4 mM"   "6 mM"   "8 mM"   "10 mM" 

Common plotting functions

species.label <- c(Sc = "S. cerevisiae", Cg = "C. glabrata")

p.survival <- list(
  geom_point(shape = 1, stroke = 1, size = 2, 
             position = position_jitter(width = 0.15)),
  stat_summary(fun = mean, fun.max = mean, fun.min = mean,
               geom = "crossbar", color = "red", width = 0.5),
  facet_wrap(~Species, scales = "free_x", labeller = as_labeller(species.label)),
  scale_y_continuous(labels = scales::percent),
  ylab("% survival"),
  theme_cowplot(line_size = 0.7, font_size = 14),
  theme(strip.text = element_text(size = rel(1), face = 3))
)

p.asr <- list(
  geom_hline(yintercept = 1, linetype = 2, color = "gray50"),
  geom_point(position = position_jitter(width = 0.1), size = 2),
  stat_summary(fun.data = "mean_cl_boot", geom = "pointrange", color = "red",
               position = position_nudge(x = 0.2)),
  facet_wrap(~Species, scales = "free_x", labeller = as_labeller(species.label)),
  theme_cowplot(line_size = 0.7),
  theme(strip.text = element_text(size = rel(1.1), face = 3))
)

Fig1: ASR between species

Goal

  • Compare the ASR effect between S. cerevisiae and C. glabrata at 10 mM and 100 mM [H2O2], respectively.

Experiment

Jinye has performed several experiments at these two concentrations, as shown below

raw %>% 
  filter(Genotype == "wt", H2O2 %in% c("10mM", "10 mM", "100mM", "100 mM"),
         Len_1 == "45 min", Group == "PO") %>% 
  mutate(group = paste(recode(Strain, yH154 = "Sc", yH001 = "Cg1", yH002 = "Cg2"), 
                       gsub(" ?mM", "", H2O2), sep = "_")) %>% 
  count(Date, group) %>% 
  pivot_wider(names_from = group, values_from = n)

We will use the 05/30/20, 06/01/20 and 06/04/20 data, which were three consecutive replicates meant to compare the ASR under -Pi between the two species. The other datasets were part of an experiment with different purposes.

Data

Main dataset:

Date Species Replicate
05/30/20 Sc, Cg 1
06/01/20 Sc, Cg 2
06/04/20 Sc, Cg 2

Note: one replicate for Sc on 05/30/20 showed much lower CFU numbers than the other plates.

filter(raw, Date == "05/30/20", Species == "Sc")

Jinye removed the second replicate for both Sc and Cg from her downstream analyses.

Below are the filtered data:

use.f1 <- paste0(c("06/04", "06/01", "05/30"), "/20")
tmp <-  raw %>%
  filter(Date %in% use.f1) %>% 
  mutate(
    scaled = Count * Dilutions * 1e-2
  ) %>% 
  # remove uninformative columns. only one H2O2 conc used for each species
  select(-Strain, -Genotype, -H2O2, -Len_1, -Len_2, -Experimenter)
  
# Assume the triplicates were paired in the order they appear in the table,
# i.e., the first row in the MO, MM, PO, PM groups belong to the same biological 
# replicate, we can derive three ASR_scores for each date x species x Len_1

dat.f1 <- tmp %>% 
  group_by(Date, Species, Group) %>%
  mutate(Repl = row_number()) %>% 
  # group by primary to calculate r (MO/MM) or r' (PO/PM)
  separate(Group, into = c("Primary", "Secondary"), sep = 1) %>% 
  group_by(Date, Species, Repl, Primary) %>% 
  # calculate % survival
  mutate(
    scaled_M = scaled[Secondary == "M"],
    r = num(scaled / scaled[Secondary == "M"], digits = 3)
  ) %>% 
  # remove the secondary mock as the information are all used
  filter(Secondary != "M") %>% 
  # 5/30/20 replicate 2 is excluded
  filter(!(Date == "05/30/20" & Repl == 2))
dat.f1

Plotting

Plot

Statistical tests

Statistical tests

  1. Determine if the basal survival rates are different between species (Wilcoxon signed-rank test)
  2. Determine if the primary stress enhanced the survival in each species (Wilcoxon signed-rank test)

Basal survival rate

The basal survival rates between species within the same day are not “paired”. We will use a rank-sum test here.

tmp <- dat.f1 %>% 
  filter(Primary == "M") %>% 
  pivot_wider(id_cols = c(Date, Repl), names_from = Species, values_from = r)
tmp
with(tmp, t.test(as.numeric(Cg), as.numeric(Sc), paired = FALSE))

    Welch Two Sample t-test

data:  as.numeric(Cg) and as.numeric(Sc)
t = 0.60672, df = 11.515, p-value = 0.5558
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.005202894  0.009192871
sample estimates:
 mean of x  mean of y 
0.01301413 0.01101914 
with(tmp, wilcox.test(Cg, Sc, paired = FALSE))

    Wilcoxon rank sum exact test

data:  Cg and Sc
W = 41, p-value = 0.3823
alternative hypothesis: true location shift is not equal to 0

basal survival rates are not significantly between species

Primary stress enhanced survival (ASR) in Cg

The comparison between r and r’ is paired. We will use a signed-rank test.

tmp <- dat.f1 %>% 
  filter(Species == "Cg") %>% 
  pivot_wider(id_cols = c(Date, Repl), names_from = Primary, values_from = r) %>% 
  mutate(ASR = P/M)
tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])
[1] "ASR_score mean = 3.44, 95% CI by bootstrap = [2.56, 4.33]"
with(tmp, t.test(as.numeric(P), as.numeric(M), paired = TRUE, alternative = "g"))

    Paired t-test

data:  as.numeric(P) and as.numeric(M)
t = 5.5041, df = 7, p-value = 0.0004513
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 0.01921734        Inf
sample estimates:
mean difference 
     0.02930431 
with(tmp, wilcox.test(P, M, paired = TRUE, alternative = "g"))

    Wilcoxon signed rank exact test

data:  P and M
V = 36, p-value = 0.003906
alternative hypothesis: true location shift is greater than 0

Primary stress no effect in Sc

tmp <- dat.f1 %>% 
  filter(Species == "Sc") %>% 
  pivot_wider(id_cols = c(Date, Repl), names_from = Primary, values_from = r) %>% 
  mutate(ASR = P/M)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)

sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])
[1] "ASR_score mean = 1.27, 95% CI by bootstrap = [0.90, 1.66]"
with(tmp, t.test(as.numeric(P), as.numeric(M), paired = TRUE, alternative = "g"))

    Paired t-test

data:  as.numeric(P) and as.numeric(M)
t = -0.10757, df = 7, p-value = 0.5413
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 -0.003806367          Inf
sample estimates:
mean difference 
  -0.0002045084 
with(tmp, wilcox.test(P, M, paired = TRUE, alternative = "g"))

    Wilcoxon signed rank exact test

data:  P and M
V = 21, p-value = 0.3711
alternative hypothesis: true location shift is greater than 0

S1A: Basal H2O2 resistance

Goal

  • Compare the basal survival rates of the two species at different [H2O2] to identify comparable concentrations for ASR.

Experiment

  • Jinye measured CFU for S. cerevisiae and C. glabrata exposed to a range of [H2O2]

Data

  • Filter the data for the relevant experiments.

Main dataset:

Species H2O2 Description
C. glabrata 0, 20, 40, 60, 80, 100 mM Only M and O, no primary stress
S. cerevisiae 0, 2, 4, 6, 8, 10 mM Only M and O, no primary stress
Date Species Replicate
03/21/22 Sc, Cg 1
03/22/22 Sc, Cg 2
03/24/22 Sc, Cg 3
03/28/22 Sc, Cg 4
04/01/22 Sc, Cg 5
use.s1 <- paste0(c("03/21", "03/22", "03/24", "03/28", "04/01"), "/22")
dat.s1 <- raw %>% select(-Experimenter, -Len_1, -Len_2, -Genotype) %>% 
  mutate(scaled = Count * Dilutions * 1e-3) %>% 
  filter(Date %in% use.s1) %>% 
  group_by(Date, Strain) %>% 
  mutate(r = num(scaled / scaled[Group == "M"], digits = 3)) %>% 
  select(-Group)
dat.s1
#write_tsv(dat.s1, file = "../input/20230302-fig-s1a-data-hb.tsv")

Plot

p <- dat.s1 %>% 
  mutate(H2O2 = gsub(" mM", "", H2O2),
         H2O2 = fct_reorder(H2O2, as.numeric(H2O2))) %>% 
  filter(H2O2 != "0") %>% 
  ggplot(aes(x = H2O2, y = r)) +
  geom_point(aes(shape = Date)) + 
  #geom_line(aes(group = Date, color = Date), alpha = 0.8) +
  scale_color_brewer(palette = "Dark2") +
  scale_shape_manual(values = 1:5, guide = "none") +
  stat_summary(fun.data = "mean_cl_boot", geom = "pointrange", color = "red2",
               size = 0.8, position = position_nudge(x = 0.3)) +
  facet_wrap(~Species, scales = "free_x", labeller = as_labeller(species.label)) +
  xlab(bquote(H[2]*O[2]~(mM))) + ylab("Basal survial rate (r)") +
  theme_cowplot(line_size = 0.7) +
  theme(strip.text = element_text(size = rel(1), face = 3))
p

#ggsave("../output/20230101-basal-survival-across-h2o2-range-sc-cg.png", width = 5, height = 3)

Statistical tests

Statistical test for difference between species at the highest concentration. Using the Wilcoxon rank-sum test (aka Mann-Whitney’s U test)

tmp <- dat.s1 %>% 
  filter(H2O2 %in% c("100 mM", "10 mM"))
tmp %>% group_by(Species) %>% summarize(mean = mean(r))

wilcox.test(r ~ Species, data = tmp, paired = FALSE)

    Wilcoxon rank sum exact test

data:  r by Species
W = 12, p-value = 1
alternative hypothesis: true location shift is not equal to 0

no significant differences at 10 vs 100 mM

S1B: ASR at different H2O2

Goal

  • Generalize the main figure finding of a stronger ASR in C. glabrata than in S. cerevisiae at a single primary stress treatment length by extending the analysis to multiple length of primary treatment

Data

Main dataset:

Species H2O2 Description
C. glabrata 0, 20, 40, 60, 80, 100 mM full ASR experiment
S. cerevisiae 0, 2, 4, 6, 8, 10mM full ASR experiment
Date Species Strain Replicate
07/16/22 Cg yH001,2 a1
07/17/22 Cg yH001,2 a2
07/18/22 Cg yH001,2 a3
07/29/22 Cg yH001 b1
07/29/22 Sc yH154 b1
08/01/22 Cg yH001 b2
08/01/22 Sc yH154 b2
08/02/22 Cg yH001 b3
08/02/22 Sc yH154 b3
08/04/22 Cg yH001 b4
08/04/22 Sc yH154 b4
08/11/22 Cg yH001 b5
08/11/22 Sc yH154 b5
use.s1b <- paste0(c("07/16", "07/17", "07/18", "07/29", "08/01", "08/02", "08/04", "08/11"), "/22")
dat.s1b <-  raw %>%
  separate(Group, into = c("Primary", "Secondary"), sep = 1) %>% 
  mutate(
    # arbitrarily decide any CFU counts < 3 are not included due to high CV
    Count = ifelse(Count < 3, NA, Count),
    scaled = Count * Dilutions * 1e-3
  ) %>% 
  filter(Date %in% use.s1b) %>% 
  group_by(Date, Strain, Primary) %>% 
  # calculate r and r'
  mutate(r = num(scaled / scaled[Secondary == "M"], digits = 3)) %>% 
  # remove the secondary mock as the information are all used
  filter(Secondary != "M") %>%
  pivot_wider(id_cols = c(Date, Strain, Species, H2O2), 
              names_from = Primary, values_from = r, names_prefix = "r") %>% 
  mutate(ASR_score = rP / rM)
  
dat.s1b
#write_tsv(dat.s1b, file = "../input/20230302-fig-s1b-data-hb.tsv")

Plot

p <- dat.s1b %>% 
  filter(!is.na(ASR_score)) %>% 
  mutate(H2O2 = gsub(" ?mM", "", H2O2),
         H2O2 = fct_reorder(H2O2, as.numeric(H2O2))) %>% 
  filter(H2O2 != "0") %>% 
  ggplot(aes(x = H2O2, y = ASR_score)) + p.asr +
  #geom_hline(yintercept = 1, linetype = 2, color = "gray50") +
  #geom_point(position = position_jitter(width = 0.1), alpha = 0.8) + 
  #stat_summary(fun.data = "mean_cl_boot", geom = "pointrange", color = "red",
  #             size = 0.8, position = position_nudge(x = 0.2)) +
  #scale_y_log10() +
  #facet_wrap(~Species, scales = "free_x", labeller = as_labeller(species.label)) +
  xlab(bquote(H[2]*O[2]~(mM))) + ylab("ASR score (r'/r)")# +
  #theme_cowplot(line_size = 0.7) +
  #theme(strip.text = element_text(size = rel(1), face = 3))
p

#ggsave("../output/20230102-ASR-score-across-h2o2-range-sc-cg.png", width = 5, height = 3)

Statistical summary

dat.s1b %>% 
  filter(!is.na(ASR_score)) %>% 
  mutate(H2O2 = gsub(" ?mM", "", H2O2),
         H2O2 = fct_reorder(H2O2, as.numeric(H2O2))) %>% 
  filter(H2O2 != "0") %>% 
  group_by(Species, H2O2) %>% 
  summarise(rM = mean(rM), ASR = mean(ASR_score), sd_asr = sd(ASR_score))
`summarise()` has grouped output by 'Species'. You can override using the `.groups` argument.

S2: ASR at different primary stress duration

Goal

  • Generalize the main figure finding of a stronger ASR in C. glabrata than in S. cerevisiae at a single [H2O2] by extending the analysis to multiple concentrations

Data

Main dataset:

Species Len_noPi H2O2 Description
C. glabrata 45, 90, 135 min 100 mM full ASR experiment
S. cerevisiae 45, 90, 135 min 10mM full ASR experiment
Date Species Len_noPi Strain
06/06/20 Cg 45 min yH001
06/06/20 Sc 45 min yH154
06/06/20 Cg 90 min yH001
06/06/20 Sc 90 min yH154
06/06/20 Cg 135 min yH001
06/06/20 Sc 135 min yH154

Supporting dataset:

Date Species Len_noPi Strain
05/30/22 Cg 45 min yH001
05/30/22 Sc 45 min yH154
06/01/22 Cg 45 min yH001
06/01/22 Sc 45 min yH154
06/04/22 Cg 45 min yH001
06/04/22 Sc 45 min yH154
use.s2 <- paste0(c("06/06", "06/04", "06/01", "05/30"), "/20")
tmp <-  raw %>%
  filter(Date %in% use.s2) %>% 
  mutate(
    # arbitrarily decide any CFU counts < 3 are not included due to high CV
    # not in use here. instead, label them in the plot (see below)
    # count = ifelse(Count < 3, NA, Count),
    scaled = Count * Dilutions * 1e-2
  ) %>% 
  # remove uninformative columns. only one H2O2 conc used for each species
  select(-Strain, -Genotype, -H2O2, -Len_2, -Experimenter)

Assume the triplicates were paired in the order they appear in the table, i.e., the first row in the MO, MM, PO, PM groups belong to the same biological replicate, we can derive three ASR_scores for each date x species x Len_1

dat.s2 <- tmp %>% 
  group_by(Date, Species, Len_1, Group) %>%
  mutate(Repl = row_number()) %>% 
  pivot_wider(id_cols = c(Date, Species, Len_1, Repl),
              names_from = Group, values_from = scaled, names_sep = "") %>% 
  mutate(
    r = MO/MM, 
    rp = PO/PM, 
    ASR_score = rp/r,
    low_count = MO < 1 # mark experiments with < 3 counts
  )
dat.s2
#write_tsv(dat.s2, file = "../input/20230302-fig-s2-data-hb.tsv")

Plot

p <- dat.s2 %>% 
  #filter(!is.na(ASR_score)) %>% 
  mutate(len_1 = factor(gsub(" ?min", "", Len_1), levels = c("45", "90", "135"))) %>% 
  ggplot(aes(x = len_1, y = ASR_score)) + p.asr +
#  geom_hline(yintercept = 1, linetype = 2, color = "gray50") +
#  geom_point(position = position_jitter(width = 0.1), size = 2) + 
#  stat_summary(position = position_nudge(x = 0.2),
#               fun.data = "mean_cl_boot", geom = "pointrange", color = "red") +
  xlab("Length of primary stress (min)") + ylab("ASR score (r'/r)") +
#  facet_wrap(~Species, scales = "free_x", labeller = as_labeller(species.label)) +
#  theme_cowplot(line_size = 0.7) +
  theme(legend.text = element_text(size = rel(1), face = 3),
        legend.position = c(0.1, 0.85),
        strip.text = element_text(size = rel(1), face = 3))
p

#ggsave("../output/20230103-ASR-score-across-noPi-length-sc-cg.png", width = 5, height = 3)

Statistical summary and test

dat.s2 %>% 
  #filter(!low_count) %>% 
  mutate(len_1 = factor(gsub(" ?min", "", Len_1), levels = c("45", "90", "135"))) %>% 
  group_by(Species, len_1) %>% 
  summarize(n = n(), ASR = mean(ASR_score), sd_asr = sd(ASR_score), .groups = "drop") %>% 
  mutate(across(where(is.double), num, sigfig = 3))

Because of the small sample size (3) for 90 and 135 minutes, Wilcoxon signed-rank test doesn’t have power to detect significant differences at any conventional size of the test (lower p-value for a sample size 3 is 0.25). Using t-test below, knowing that the normal assumption is likely not met. Overall, we should focus on the trend and not the statistical significance in this result.

dat.s2 %>% 
  ungroup() %>% 
  mutate(len_1 = factor(gsub(" ?min", "", Len_1), levels = c("45", "90", "135"))) %>% 
  select(Species, len_1, r, rp) %>% 
  nest(data = c(r, rp)) %>% 
  mutate(
    test = map(data, ~ t.test(.x$rp, .x$r, paired = TRUE, alternative = "g")),
    tidied = map(test, tidy)
  ) %>% 
  unnest(tidied) %>% 
  select(Species, len_1, p.value, method, alternative) %>% 
  mutate(p.bonf = p.adjust(p.value, method = "bonf"),
         p.holm = p.adjust(p.value, method = "holm"),
         p.hoch = p.adjust(p.value, method = "hoch"),
         across(starts_with("p."), round, digits = 5)) %>% 
  arrange(Species, len_1)
p <- dat.s2 %>% 
  #filter(!is.na(ASR_score)) %>% 
  mutate(len_1 = factor(Len_1, levels = c("45 min", "90 min", "135 min"))) %>% 
  ggplot(aes(x = Species, y = ASR_score)) +
  geom_point(#aes(fill = low_count),
    position = position_jitter(0.1), size = 1.5, shape = 21) + 
  stat_summary(fun.data = "mean_se", geom = "pointrange", color = "red") +
  #scale_y_log10() +
  scale_shape_manual(values = c(21,22), labels = species.label) +
  #scale_fill_manual(values = c("white", "gray40"), guide = "none") +
  #facet_wrap(~Species, scales = "free_x", labeller = as_labeller(species.label)) +
  facet_wrap(~ len_1, scales = "free") +
  xlab("Length of primary stress (min)") + ylab("ASR score (r'/r)") +
  theme_cowplot(line_size = 0.7)
p

#ggsave("../output/20230103-ASR-score-across-noPi-length-sep-panel.png", width = 6, height = 3)

S3a: tBOOH

Goal

  • Determine if phosphate starvation also provides ASR for other oxidants than H2O2

Experiment

  • Hanxi tested tert-butyl hydroperoxide (tBOOH), menadione and menadione sodium bisulfite (MSB), following the same procedure as Jinye did for H2O2

Data

Main dataset:

Species Oxidant Concentration #Reps Dates
C. glabrata tBOOH 0, 1, 1.5, 2 mM 6 8/23-8/31
C. glabrata Menadione 0, 250, 300, 350 uM 6 7/17-7/26
C. glabrata MSB 0, 300, 350, 400 mM 6 9/3-9/8

Analysis

Read and format data

tmp <- read_tsv("../input/20230901-tBOOH-ASR-CFU-ht.tsv",
                col_types = cols(), comment = "#") %>% 
  mutate(
    scaled = Count * Dilutions * 1e-2
  )

dat.s3a <- tmp %>% 
  # remove the phosphate starvation experiments - they were included as positive
  # controls, but because there is only one replicate and the secondary stress
  # was applied for 3 instead of 2 hours, CFU is extremely low and not conclusive
  filter(Len_2 != "3 hr") %>% 
  # remove uninformative / nonvariable columns 
  select(-Len_1, -Len_2, -Species, -Strain) %>% 
  # group by experiment and [tBOOh] to calculate r (MO/MM) or r' (PO/PM)
  separate(Group, into = c("Primary", "Secondary"), sep = 1) %>% 
  group_by(Date, Primary) %>% 
  # calculate % survival
  mutate(scaled_M = scaled[Secondary == "M"],
         r = num(scaled / scaled[Secondary == "M"], digits = 3)) %>% 
  # remove the secondary mock as the information are all used
  filter(Secondary != "M") %>% 
  mutate(
    Primary = factor(Primary, levels = c("M", "P"), 
                     labels = c("Mock", "-Pi")),
    tBOOH = factor(tBOOH, levels = c("0.5 mM", "1 mM", "1.5 mM", "2 mM"))
  )
dat.s3a

Plot (all data)

dat.s3a %>% 
  # leave out the lowest concentration in each group
  #filter(!H2O2 %in% c("2 mM", "60 mM")) %>% 
  ggplot(aes(x = tBOOH, y = r)) + #p.survival[-3] +
  geom_point(aes(shape = Primary), stroke = 1, size = 2, 
             position = position_dodge(0.7)) +
  stat_summary(aes(group = Primary), position = position_dodge(0.7),
               fun = mean, fun.max = mean, fun.min = mean,
               geom = "crossbar", color = "red", width = 0.5) +
  facet_wrap(~ tBOOH, nrow = 1, scales = "free_x") +
  scale_shape_manual(values = c("Mock" = 1, "-Pi" = 16)) +
  scale_y_continuous(labels = scales::percent) +
  xlab("tBOOH") + ylab("% survival") +
  theme_bw(base_size = 14, base_line_size = 1) +
  panel_border(color = "black", size = 1) +
  theme(strip.text = element_text(size = rel(1), face = 3),
        strip.background = element_blank())

From the plot, it is clear that phosphate starvation does NOT provide ASR for tBOOH below we will focus on the 2 mM dataset, as the basal survival rate is ~5%

Statistical test for ASR

tmp <- dat.s3a %>% 
  filter(tBOOH == "2 mM") %>% 
  pivot_wider(id_cols = Date, names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/`Mock`)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)

sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])
[1] "ASR_score mean = 0.71, 95% CI by bootstrap = [0.49, 0.88]"
with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))

    Paired t-test

data:  as.numeric(`-Pi`) and as.numeric(Mock)
t = -2.9394, df = 5, p-value = 0.9839
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 -0.02271145         Inf
sample estimates:
mean difference 
    -0.01347428 
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

    Wilcoxon signed rank exact test

data:  -Pi and Mock
V = 0, p-value = 1
alternative hypothesis: true location shift is greater than 0

S3b: Menadione

Goal

  • Determine if phosphate starvation also provides ASR for other oxidants than H2O2

Experiment

  • Hanxi tested tert-butyl hydroperoxide (tBOOH), menadione and menadione sodium bisulfite (MSB), following the same procedure as Jinye did for H2O2

Analysis

Read and format data

tmp <- read_tsv("../input/20230801-menadione-ASR-CFU-ht.tsv",
                col_types = cols(), comment = "#") %>% 
  mutate(
    scaled = Count * Dilutions * 1e-2
  )

dat.s3b <- tmp %>% 
  # remove uninformative / nonvariable columns 
  select(-Len_1, -Len_2, -Species, -Strain) %>% 
  # group by experiment and [tBOOh] to calculate r (MO/MM) or r' (PO/PM)
  separate(Group, into = c("Primary", "Secondary"), sep = 1) %>% 
  group_by(Date, Primary) %>% 
  # calculate % survival
  mutate(scaled_M = scaled[Secondary == "M"],
         r = scaled / scaled[Secondary == "M"]) %>% 
  # remove the secondary mock as the information are all used
  filter(Secondary != "M") %>% 
  mutate(
    Primary = factor(Primary, levels = c("M", "P"), 
                     labels = c("Mock", "-Pi")),
    Concentration = factor(Concentration,
                           levels = c("250 uM", "300 uM", "350 uM",
                                      "400 uM", "450 uM")),
    Flag = Count < 10
  ) %>% 
  rename(Menadione = Concentration)
dat.s3b

Plot (all data)

dat.s3b %>% 
  # leave out the lowest concentration in each group
  #filter(!H2O2 %in% c("2 mM", "60 mM")) %>% 
  ggplot(aes(x = Menadione, y = r)) + #p.survival[-3] +
  geom_point(aes(shape = Primary, color = Flag), stroke = 1, size = 2, 
             position = position_dodge(0.7)) +
  stat_summary(aes(group = Primary),
               position = position_dodge(0.7),
               fun = mean, fun.max = mean, fun.min = mean,
               geom = "crossbar", color = "red", width = 0.5) +
  facet_wrap(~ Menadione, nrow = 1, scales = "free_x") +
  scale_shape_manual(values = c("Mock" = 1, "-Pi" = 16)) +
  scale_color_manual("Count < 10", values = c("gray10", "green3")) +
  scale_y_continuous(labels = scales::percent) +
  xlab("Menadione") + ylab("% survival") +
  theme_bw(base_size = 14, base_line_size = 1) +
  panel_border(color = "black", size = 1) +
  theme(axis.text.x = element_blank(),
        strip.text = element_text(size = rel(1), face = 3),
        strip.background = element_blank())

the whole concentration series shows consistent trend of ASR. 400 uM would have been a good concentration to focus on, but we don’t have enough replicates at this concentration

Statistical test for ASR

We focus on 350 uM set because it shows ASR and have 5 usable replicates.

tmp <- dat.s3b %>% 
  filter(Menadione == "350 uM", !Flag) %>% 
  pivot_wider(id_cols = Date, names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/`Mock`) %>% 
  na.omit()

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)

sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])
[1] "ASR_score mean = 2.96, 95% CI by bootstrap = [1.52, 4.88]"
with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))

    Paired t-test

data:  as.numeric(`-Pi`) and as.numeric(Mock)
t = 2.5106, df = 4, p-value = 0.03301
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 0.02443896        Inf
sample estimates:
mean difference 
      0.1620079 
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

    Wilcoxon signed rank exact test

data:  -Pi and Mock
V = 15, p-value = 0.03125
alternative hypothesis: true location shift is greater than 0

S3b: Menadione sodium bisulfite

Goal

  • Determine if phosphate starvation also provides ASR for other oxidants than H2O2

Experiment

  • Hanxi tested tert-butyl hydroperoxide (tBOOH), menadione and menadione sodium bisulfite (MSB), following the same procedure as Jinye did for H2O2

Analysis

Read and format data

Note that we will overwrite dat.s3b.

tmp <- read_tsv("../input/20230910-MSB-ASR-CFU-ht.tsv",
                col_types = cols(), comment = "#") %>% 
  mutate(
    scaled = Count * Dilutions * 1e-2
  )

dat.s3b <- tmp %>% 
  # remove the phosphate starvation experiments - they were included as positive
  # controls, but because there is only one replicate and the secondary stress
  # was applied for 3 instead of 2 hours, CFU is extremely low and not conclusive
  filter(Len_2 != "3 hr") %>% 
  # remove uninformative / nonvariable columns 
  select(-Len_1, -Len_2, -Species, -Strain) %>% 
  # group by experiment and [tBOOh] to calculate r (MO/MM) or r' (PO/PM)
  separate(Group, into = c("Primary", "Secondary"), sep = 1) %>% 
  group_by(Date, Primary) %>% 
  # calculate % survival
  mutate(scaled_M = scaled[Secondary == "M"],
         r = num(scaled / scaled[Secondary == "M"], digits = 3)) %>% 
  # remove the secondary mock as the information are all used
  filter(Secondary != "M") %>% 
  mutate(
    Primary = factor(Primary, levels = c("M", "P"), 
                     labels = c("Mock", "-Pi")),
    Menadione = factor(Concentration, levels = c("300 mM", "350 mM", "400 mM", "60mM H2O2"))
  )
dat.s3b

Plot (all data)

dat.s3b %>% 
  # leave out the lowest concentration in each group
  #filter(!H2O2 %in% c("2 mM", "60 mM")) %>% 
  ggplot(aes(x = Menadione, y = r)) + #p.survival[-3] +
  geom_point(aes(shape = Primary), stroke = 1, size = 2, 
             position = position_dodge(0.7)) +
  stat_summary(aes(group = Primary), position = position_dodge(0.7),
               fun = mean, fun.max = mean, fun.min = mean,
               geom = "crossbar", color = "red", width = 0.5) +
  facet_wrap(~ Menadione, nrow = 1, scales = "free_x") +
  scale_shape_manual(values = c("Mock" = 1, "-Pi" = 16)) +
  scale_y_continuous(labels = scales::percent) +
  xlab("MSB") + ylab("% survival") +
  theme_bw(base_size = 14, base_line_size = 1) +
  panel_border(color = "black", size = 1) +
  theme(strip.text = element_text(size = rel(1), face = 3),
        strip.background = element_blank())

at the highest, 400 mM concentration, there seems to be ASR below we will focus on the 400 mM dataset, where the basal survival rate is ~1%

Plot (combine with tBOOH)

dat.s3ab <- bind_rows(
  tBOOH = dat.s3a %>% filter(tBOOH == "2 mM") %>% rename(Concentration = tBOOH),
  MSB = dat.s3b %>% filter(Concentration == "400 mM") %>% select(-Menadione),
  H2O2 = dat.s3b %>% filter(Concentration == "60mM H2O2") %>% select(-Menadione),
  .id = "ROS"
) %>% 
 mutate(Concentration = gsub("60mM H2O2", "60 mM", Concentration),
        ROS = factor(ROS, levels = c("tBOOH", "MSB", "H2O2"),
                     labels = c("tBOOH", "MSB", "H[2]*O[2]"))) 
dat.s3ab %>% 
  ggplot(aes(x = Concentration, y = r)) + #p.survival[-3] +
  geom_point(aes(shape = Primary), stroke = 1, size = 2, 
             position = position_dodge(0.7)) +
  stat_summary(aes(group = Primary), position = position_dodge(0.7),
               fun = mean, fun.max = mean, fun.min = mean,
               geom = "crossbar", color = "red", width = 0.5) +
  facet_wrap(~ ROS, nrow = 1, scales = "free_x", labeller = label_parsed) +
  scale_shape_manual(values = c("Mock" = 1, "-Pi" = 16)) +
  scale_y_continuous(labels = scales::percent) +
  xlab(NULL) + ylab("% survival") +
  theme_bw(base_size = 14, base_line_size = 1) +
  background_grid(major = "none") +
  panel_border(color = "black", size = 1) +
  theme(strip.text = element_text(size = rel(1), face = 3),
        strip.background = element_blank())
ggsave("../output/20230912-figs3-other-ros.png", width = 5, height = 3)

Statistical test for ASR

We focus on 400 mM set because it shows the most clear ASR effect. Note that a test done for the 350 mM, which leads to a similar 5% basal survival rate as 2 mM tBOOH, showed a moderate ASR (mean = 1.55) effect, with a P-value approaching 0.05 (0.08). Jinye’s spotting assay also showed clear ASR result at 350 mM.

tmp <- dat.s3b %>% 
  filter(Menadione == "400 mM") %>% 
  pivot_wider(id_cols = Date, names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/`Mock`)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)

sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])
[1] "ASR_score mean = 2.41, 95% CI by bootstrap = [1.79, 3.00]"
with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))

    Paired t-test

data:  as.numeric(`-Pi`) and as.numeric(Mock)
t = 3.0552, df = 5, p-value = 0.01413
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 0.007146316         Inf
sample estimates:
mean difference 
     0.02099059 
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

    Wilcoxon signed rank exact test

data:  -Pi and Mock
V = 21, p-value = 0.01563
alternative hypothesis: true location shift is greater than 0

In the same experiment, ASR for H2O2 was confirmed:

tmp <- dat.s3b %>% 
  filter(Menadione == "60mM H2O2") %>% 
  pivot_wider(id_cols = Date, names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/`Mock`)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)

sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])
[1] "ASR_score mean = 16.40, 95% CI by bootstrap = [7.28, 25.30]"
with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))

    Paired t-test

data:  as.numeric(`-Pi`) and as.numeric(Mock)
t = 4.3054, df = 4, p-value = 0.006296
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 0.06709178        Inf
sample estimates:
mean difference 
      0.1328976 
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

    Wilcoxon signed rank exact test

data:  -Pi and Mock
V = 15, p-value = 0.03125
alternative hypothesis: true location shift is greater than 0

Fig3: cta1∆

Goal

  • Determine if CTA1 is required for the ASR

Experiment

  • Jinye deleted CTA1 and compared ASR in this strain to the wt C. glabrata

Data

Species Strain Genotype H2O2
C. glabrata yH001, yH002 wildtype 80, 100 mM
C. glabrata yH271, yH272 cta1∆ 2.2, 2.5 mM

Six replicates, two each from 07/08, 07/11, 07/12 of 2022.

use.f3 <- paste0(c("07/08", "07/11", "07/12"), "/22")
tmp <-  raw %>%
  filter(Date %in% use.f3) %>% 
  mutate(
    scaled = Count * Dilutions * 1e-2
  ) %>% 
  # remove uninformative columns. only one H2O2 conc used for each species
  select(-Len_1, -Len_2, -Experimenter)
# Assume the replicates were paired in the order they appear in the table,
# i.e., the first row in the MO, MM, PO, PM groups belong to the same biological 
# replicate, we can derive three ASR_scores for each date x species x Len_1

dat.f3 <- tmp %>% 
  # group by primary to calculate r (MO/MM) or r' (PO/PM)
  separate(Group, into = c("Primary", "Secondary"), sep = 1) %>% 
  group_by(Date, Strain, Primary) %>% 
  # calculate % survival
  mutate(scaled_M = scaled[Secondary == "M"],
         r = num(scaled / scaled[Secondary == "M"], digits = 3)) %>% 
  # remove the secondary mock as the information are all used
  filter(Secondary != "M")
dat.f3

Plot (all data)

dat.f3 %>% 
  mutate(
    Primary = factor(Primary, levels = c("M", "P"), 
                     labels = c("Mock", "-Pi")),
    Genotype = factor(Genotype, levels = c("wt", "cta1Δ"),
                      labels = c("wildtype", "cta1Δ")),
    Group = factor(H2O2, levels = c("100 mM", "2.5 mM", "80 mM", "2.2 mM"),
                   labels = c("High", "High", "Medium", "Medium"))
  ) %>%
  ggplot(aes(x = H2O2, y = r)) + #p.survival[-3] +
  geom_point(aes(shape = Primary), stroke = 1, size = 2, 
             position = position_dodge(0.9)) +
  stat_summary(aes(group = Primary), position = position_dodge(0.9),
               fun = mean, fun.max = mean, fun.min = mean,
               geom = "crossbar", color = "red", width = 0.5) +
  facet_wrap(~ Group + Genotype, nrow = 1, scales = "free_x") +
  scale_shape_manual(values = c("Mock" = 1, "-Pi" = 16)) +
  scale_y_continuous(labels = scales::percent) +
  xlab(bquote(H[2]*O[2]~(mM))) + ylab("% survival") +
  theme_bw(base_size = 14, base_line_size = 1) +
  panel_border(color = "black", size = 1) +
  theme(strip.text = element_text(size = rel(1), face = 3),
        strip.background = element_blank())

100 vs 2.5 mM

To be consistent with panel C, we will use the 100 mM vs 2.5 mM pair and leave out the 80 mM vs 2.2 mM pair.

dat.f3a <- dat.f3 %>% 
  mutate( Primary = factor(Primary, levels = c("M", "P"), 
                           labels = c("Mock", "-Pi")),
          Genotype = factor(Genotype, levels = c("wt", "cta1Δ"),
                            labels = c("wildtype", "cta1Δ")),
          Group = factor(H2O2, levels = c("100 mM", "2.5 mM", "80 mM", "2.2 mM"),
                         labels = c("High", "High", "Medium", "Medium"))) %>%
  filter(Group == "High") %>% 
  select(-Group) %>% 
  ungroup()
#write_tsv(dat.f3a, file = "../input/20230520-fig-3d-data-hb.tsv")

Plot

p <- dat.f3a %>% 
  mutate(Genotype = fct_recode(Genotype, "WT" = "wildtype")) %>% 
  ggplot(aes(x = Primary, y = r)) +
  geom_point(aes(shape = Primary), stroke = 1, size = 2,
             position = position_jitter(0.1)) +
  scale_shape_manual(name = "", values = c(1, 16), guide = "none") +
  #scale_fill_manual(name = bquote(H[2]*O[2]), values = c("white", "gray80")) +
  p.survival[-1] +
  facet_wrap(~Genotype + H2O2, nrow = 1) +
  panel_border(color = "black", size = 1.5) +
  theme(axis.line = element_blank(),
        axis.title.x = element_blank(), 
        strip.background = element_blank()
        )
p


#ggsave("../output/20230301-fig3d-asr-cta1.png", width = 3.3, height = 3)
p <- ggplot(dat.f3a, aes(x = H2O2, y = r)) +
  geom_point(aes(shape = Primary), stroke = 0.9, size = 2.5, 
             position = position_jitterdodge(jitter.width = 0.3, dodge.width = 0.9)) +
  stat_summary(aes(group = Primary), position = position_dodge(0.9),
               fun = mean, fun.max = mean, fun.min = mean,
               geom = "crossbar", color = "red", width = 0.5) +
  facet_wrap(~ Genotype, nrow = 1, scales = "free_x") +
  scale_shape_manual(name = "Primary stress", values = c("Mock" = 1, "-Pi" = 16)) +
  scale_y_continuous(labels = scales::percent) +
  xlab(bquote(H[2]*O[2]~(mM))) + ylab("% survival") +
  theme_cowplot(line_size = 1.2) +
  panel_border(color = "black", size = 1.5) +
  theme(strip.text = element_text(size = rel(1)),
        strip.background = element_blank(),
        #strip.placement = "inside",
        axis.line = element_blank(),
        axis.ticks.x = element_blank(),
        legend.position = "top",
        legend.justification = "center",
        legend.margin = margin(b = -10),
        legend.text = element_text(size = rel(0.9)),
        legend.title = element_text(size = rel(0.9)))
p

ggsave("../output/20230301-fig3d-asr-cta1.png", width = 3.5, height = 3.5)

Statistical tests

Statistical test

  1. Determine if the basal survival rates are different between wt and cta1∆ (Wilcoxon signed-rank test)
  2. Determine if the primary stress enhanced the survival in each genotype (Wilcoxon signed-rank test)

Basal survival rate

Between wt and cta1∆, unpaired, rank-sum test.

tmp <- dat.f3a %>% 
  filter(Primary == "Mock") %>% 
  select(Date, Genotype, r) %>% 
  arrange(Genotype)

tmp %>% group_by(Genotype) %>% summarize(mean = mean(r), sd = num(sd(r), digits = 3))

wilcox.test(r ~ Genotype, paired = FALSE, data = tmp)

    Wilcoxon rank sum exact test

data:  r by Genotype
W = 12, p-value = 0.3939
alternative hypothesis: true location shift is not equal to 0

basal survival rates not significantly different between genotypes at the chosen [H2O2]

Survival rate with the primary stress

Between wt and cta1∆, unpaired, rank-sum test.

tmp <- dat.f3a %>% 
  filter(Primary == "-Pi") %>% 
  select(Date, Genotype, r) %>% 
  arrange(Genotype)

tmp %>% group_by(Genotype) %>% summarize(mean = mean(r), sd = num(sd(r), digits = 3))

wilcox.test(r ~ Genotype, paired = FALSE, data = tmp)

    Wilcoxon rank sum exact test

data:  r by Genotype
W = 36, p-value = 0.002165
alternative hypothesis: true location shift is not equal to 0

survival rates with primary stress significantly different between wt and cta1∆

Primary stress enhanced in wildtype

Comparison between r and r’, paired, signed-rank test.

tmp <- dat.f3a %>% 
  filter(Genotype == "wildtype") %>% 
  pivot_wider(id_cols = c(Date, Strain), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])

with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))
with(tmp, wilcox.test(`-Pi`, Mock, paired = FALSE, alternative = "g"))

Primary stress effect in cta1Δ

Paired, signed-rank test

tmp <- dat.f3a %>% 
  filter(Genotype == "cta1Δ") %>% 
  pivot_wider(id_cols = c(Date, Strain), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])

with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))
with(tmp, wilcox.test(`-Pi`, Mock, paired = FALSE, alternative = "g"))

There is a statistically significant ASR effect in cta1∆, but the effect is very mild

Comparing the ASR effect in cta1Δ vs wild type

Unpaired, rank-sum test

tmp <- dat.f3a %>% 
  #filter(Genotype == "cta1Δ") %>% 
  pivot_wider(id_cols = c(Date, Strain, Genotype), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock) %>% 
  arrange(Genotype)

tmp %>% group_by(Genotype) %>% 
  summarize(ASR_score = paste(round(as.numeric(ASR),1), collapse = ", "), 
            mean = mean(ASR), sd = sd(ASR))

t.test(as.numeric(ASR) ~ Genotype, paired = FALSE, data = tmp)
wilcox.test(as.numeric(ASR) ~ Genotype, paired = FALSE, data = tmp)

The difference in ASR-score between cta1∆ and wild type is significant (P = 0.002)

80 vs 2.2 mM

Corresponding results for 80 mM vs 2.2 mM

dat.f3b <- dat.f3 %>% 
  mutate( Primary = factor(Primary, levels = c("M", "P"), 
                           labels = c("Mock", "-Pi")),
          Genotype = factor(Genotype, levels = c("wt", "cta1Δ"),
                            labels = c("wildtype", "cta1Δ")),
          Group = factor(H2O2, levels = c("100 mM", "2.5 mM", "80 mM", "2.2 mM"),
                         labels = c("High", "High", "Medium", "Medium"))) %>%
  filter(Group == "Medium") %>% 
  ungroup()

Plot

p <- ggplot(dat.f3b, aes(x = H2O2, y = r)) +
  geom_point(aes(shape = Primary), stroke = 0.9, size = 2.5, 
             position = position_jitterdodge(jitter.width = 0.3, dodge.width = 0.9)) +
  stat_summary(aes(group = Primary), position = position_dodge(0.9),
               fun = mean, fun.max = mean, fun.min = mean,
               geom = "crossbar", color = "red", width = 0.5) +
  facet_wrap(~ Genotype, nrow = 1, scales = "free_x") +
  scale_shape_manual(name = "Primary stress", values = c("Mock" = 1, "-Pi" = 16)) +
  scale_y_continuous(labels = scales::percent) +
  xlab(bquote(H[2]*O[2]~(mM))) + ylab("% survival") +
  theme_cowplot(line_size = 1.2) +
  panel_border(color = "black", size = 1) +
  theme(strip.text = element_text(size = rel(1)),
        strip.background = element_blank(),
        #strip.placement = "inside",
        axis.line = element_blank(),
        axis.ticks.x = element_blank(),
        legend.position = "top",
        legend.justification = "center",
        legend.margin = margin(b = -10),
        legend.text = element_text(size = rel(0.9)),
        legend.title = element_text(size = rel(0.9)))
p


#ggsave("../output/20230301-f3b-asr-cta1.png", width = 3.5, height = 3.5)

Statistical tests

Statistical test

  1. Determine if the basal survival rates are different between wt and cta1∆ (Wilcoxon signed-rank test)
  2. Determine if the primary stress enhanced the survival in each genotype (Wilcoxon signed-rank test)

Basal survival rate Between genotypes, unpaired, rank-sum test.

tmp <- dat.f3b %>% 
  filter(Primary == "Mock") %>% 
  select(Date, Genotype, r) %>% 
  arrange(Genotype)
tmp %>% group_by(Genotype) %>% summarize(mean = mean(r), sd = num(sd(r), digits = 3))
wilcox.test(r ~ Genotype, paired = FALSE, data = tmp)

    Wilcoxon rank sum exact test

data:  r by Genotype
W = 7, p-value = 0.09307
alternative hypothesis: true location shift is not equal to 0

the basal survival rate is slightly higher in cta1∆. the difference is not statistically significant at a conventional 0.05 level.

Primary stress enhanced in wildtype

Comparison between r and r’, paired, signed-rank test.

tmp <- dat.f3b %>% 
  filter(Genotype == "wildtype") %>% 
  pivot_wider(id_cols = c(Date, Strain), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])
[1] "ASR_score mean = 4.46, 95% CI by bootstrap = [3.76, 5.16]"
with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))

    Paired t-test

data:  as.numeric(`-Pi`) and as.numeric(Mock)
t = 8.9447, df = 5, p-value = 0.0001455
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 0.09212352        Inf
sample estimates:
mean difference 
      0.1189116 
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

    Wilcoxon signed rank exact test

data:  -Pi and Mock
V = 21, p-value = 0.01563
alternative hypothesis: true location shift is greater than 0

Primary stress effect in cta1Δ

Paired, signed-rank test

tmp <- dat.f3b %>% 
  filter(Genotype == "cta1Δ") %>% 
  pivot_wider(id_cols = c(Date, Strain), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])
[1] "ASR_score mean = 0.93, 95% CI by bootstrap = [0.57, 1.40]"
with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))

    Paired t-test

data:  as.numeric(`-Pi`) and as.numeric(Mock)
t = -0.84267, df = 5, p-value = 0.7811
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 -0.02818646         Inf
sample estimates:
mean difference 
    -0.00831149 
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

    Wilcoxon signed rank exact test

data:  -Pi and Mock
V = 7, p-value = 0.7812
alternative hypothesis: true location shift is greater than 0

no significant effect of ASR in cta1∆ at this [H2O2] concentration.

Comparing the ASR effect in cta1Δ vs wild type

Unpaired, rank-sum test

tmp <- dat.f3b %>% 
  #filter(Genotype == "cta1Δ") %>% 
  pivot_wider(id_cols = c(Date, Strain, Genotype), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock) %>% 
  arrange(Genotype)

tmp %>% group_by(Genotype) %>% 
  summarize(ASR_score = paste(round(as.numeric(ASR),1), collapse = ", "), 
            mean = mean(ASR), sd = sd(ASR))

t.test(as.numeric(ASR) ~ Genotype, paired = FALSE, data = tmp)

    Welch Two Sample t-test

data:  as.numeric(ASR) by Genotype
t = 7.5856, df = 8.1316, p-value = 5.858e-05
alternative hypothesis: true difference in means between group wildtype and group cta1Δ is not equal to 0
95 percent confidence interval:
 2.460004 4.600269
sample estimates:
mean in group wildtype    mean in group cta1Δ 
             4.4588479              0.9287116 
wilcox.test(as.numeric(ASR) ~ Genotype, paired = FALSE, data = tmp)

    Wilcoxon rank sum exact test

data:  as.numeric(ASR) by Genotype
W = 36, p-value = 0.002165
alternative hypothesis: true location shift is not equal to 0

The difference in ASR-score between the cta1∆ and wild type is significant (P = 0.002)

Fig3-S1: CTA1 complementation

Goal

  • Validate that cta1∆ result is due to the intended deletion

Experiment

  • Jinye constructed a CTA1 complementation strain by putting the gene’s CDS back to its endogenous locus.
  • Hanxi performed ASR to compare the ASR effect size of the complementation, the deletion and the wild type.

Data

Species Strain Genotype H2O2
C. glabrata yH181 wildtype 60, 80, 100 mM
C. glabrata yH271 cta1∆ 2., 2.5, 3. mM
C. glabrata yH285 cta1::CTA1. 60, 80, 100 mM

Six replicates, between 7/31/23 - 8/4/23

Analysis

Read and format data

tmp <- read_tsv("../input/20230806-fig-3sup-cta1-comp-data-ht.tsv",
                col_types = cols(), comment = "#") %>% 
  mutate(
    scaled = Count * Dilutions * 1e-2
  )

dat.f3s <- tmp %>% 
  # remove uninformative columns. only one H2O2 conc used for each species
  select(-Len_1, -Len_2, -Species) %>% 
  # group by experiment and H2O2 to calculate r (MO/MM) or r' (PO/PM)
  separate(Group, into = c("Primary", "Secondary"), sep = 1) %>% 
  group_by(Index, Strain, Primary) %>% 
  # calculate % survival
  mutate(scaled_M = scaled[Secondary == "M"],
         r = num(scaled / scaled[Secondary == "M"], digits = 3)) %>% 
  # remove the secondary mock as the information are all used
  filter(Secondary != "M")
dat.f3s

Plot (exclude 60 mM/2 mM)

dat.f3s %>% 
  # leave out the lowest concentration in each group
  filter(!H2O2 %in% c("2 mM", "60 mM")) %>% 
  mutate(
    Primary = factor(Primary, levels = c("M", "P"), 
                     labels = c("Mock", "-Pi")),
    Genotype = factor(Genotype, levels = c("wt", "Cgcta1::CgCTA1", "cta1::URA3"),
                      labels = c("wildtype", "cta1::CTA1", "cta1Δ"))
  ) %>%
  ggplot(aes(x = H2O2, y = r)) + #p.survival[-3] +
  geom_point(aes(shape = Primary), stroke = 1, size = 2, 
             position = position_dodge(0.7)) +
  stat_summary(aes(group = Primary), position = position_dodge(0.7),
               fun = mean, fun.max = mean, fun.min = mean,
               geom = "crossbar", color = "red", width = 0.5) +
  facet_wrap(~ Genotype, nrow = 1, scales = "free_x") +
  scale_shape_manual(values = c("Mock" = 1, "-Pi" = 16)) +
  scale_y_continuous(labels = scales::percent) +
  xlab("Primary stress (45 min)") + ylab("% survival") +
  theme_bw(base_size = 14, base_line_size = 1) +
  panel_border(color = "black", size = 1) +
  theme(strip.text = element_text(size = rel(1), face = 3),
        strip.background = element_blank(),
        legend.position = c(0.9, 0.8),
        legend.background = element_blank())

80 v 100 v 3 mM

By trial and error, I found 80 mM for the wildtype, 100 mM for the complement strain and 3 mM for the deletion had relatively similar basal survival rates.

dat.f3s1 <- dat.f3s %>% 
  mutate(Group = paste(Genotype, H2O2, sep = "_")) %>% 
  #filter(H2O2 %in% c("100 mM", "3 mM")) %>% 
  filter(Group %in% c("wt_80 mM", "Cgcta1::CgCTA1_100 mM", "cta1::URA3_3 mM")) %>% 
  select(-Group) %>% 
  mutate(
    Primary = factor(Primary, levels = c("M", "P"), 
                     labels = c("Mock", "-Pi")),
    Genotype = factor(Genotype, levels = c("wt", "Cgcta1::CgCTA1", "cta1::URA3"),
                      labels = c("wildtype", "cta1::CTA1", "cta1Δ")))
#write_tsv(dat.f3a, file = "../input/20230520-fig-3d-data-hb.tsv")

Plot

p <- dat.f3s1 %>% 
  mutate(Genotype = fct_recode(Genotype, "WT" = "wildtype")) %>% 
  ggplot(aes(x = Primary, y = r)) +
  geom_point(aes(shape = Primary), stroke = 1, size = 2,
             position = position_jitter(0.1)) +
  scale_shape_manual(name = "", values = c(1, 16), guide = "none") +
  #scale_fill_manual(name = bquote(H[2]*O[2]), values = c("white", "gray80")) +
  p.survival[-1] +
  facet_wrap(~Genotype + H2O2, nrow = 1) +
  panel_border(color = "black", size = 1.5) +
  theme(axis.line = element_blank(),
        axis.title.x = element_blank(), 
        strip.background = element_blank()
        )
p


#ggsave("../output/20230806-fig3sup-asr-cta1-comp-1.png", width = 5, height = 3)
#p <- 
dat.f3s1 %>% 
  mutate( 
    Genotype = fct_recode(Genotype, "WT" = "wildtype"),
    Group = paste(Genotype, H2O2, sep = "\n"),
    r = as.numeric(r)) %>% 
  pivot_wider(id_cols = c(Index, Group), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi` / Mock, Group = fct_relevel(Group, "WT\n80 mM")) %>% 
  ggplot(aes(x = Group, y = ASR)) +
  geom_point(stroke = 1, size = 2,
             position = position_jitter(0.1)) +
  stat_summary(fun = mean, fun.max = mean, fun.min = mean,
               geom = "crossbar", color = "red", width = 0.5) +
  scale_y_continuous(labels = scales::percent) +
  ylab("% survival") +
  theme_cowplot(line_size = 0.7, font_size = 14) +
  panel_border(color = "black", size = 1.5) +
  theme(axis.line = element_blank(),
        axis.title.x = element_blank(),
        axis.text.x = element_text(face = 2, size = rel(1.2)),
        strip.background = element_blank()
        )

Statistical test

  1. Determine if the basal survival rates are different between genotypes (Wilcoxon signed-rank test)
  2. Determine if the primary stress enhanced the survival in each genotype (Wilcoxon signed-rank test)

Basal survival rate

Because we have three groups here, my strategy is to first perform an ANOVA-like, but rank-based, Krusal-Wallis test, where the null hypothesis is that all three groups’ distribution has the same “location” (=mean). I also performed a pairwise Wilcoxson rank sum test, although that is not necessary if the first test is deemed insignificant.

tmp <- dat.f3s1 %>% 
  filter(Primary == "Mock") %>% 
  select(Index, Genotype, r) %>% 
  mutate(r = as.double(r)) %>% 
  arrange(Genotype)
Adding missing grouping variables: `Strain`, `Primary`
tmp %>% group_by(Genotype) %>% summarize(mean = mean(r), sd = num(sd(r), digits = 3))

kruskal.test(r ~ Genotype, data = tmp)

    Kruskal-Wallis rank sum test

data:  r by Genotype
Kruskal-Wallis chi-squared = 1.9268, df = 2, p-value = 0.3816
pairwise.wilcox.test(x = tmp$r, g = tmp$Genotype)

    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  tmp$r and tmp$Genotype 

           wildtype cta1::CTA1
cta1::CTA1 0.4      -         
cta1Δ      1.0      1.0       

P value adjustment method: holm 

basal survival rates not significantly different between genotypes at the chosen [H2O2], as shown by both the (ANOVA-equivalent, rank-based) Kruskal-Wallis test and the (t-test equivalent) pairwise Wilcoxson rank-sum test (unpaired). P-values from the latter were adjusted for multiple comparison using Holm’s method (uniformly more powerful than Bonferroni)

Survival rate with the primary stress

Same strategy as above

tmp <- dat.f3s1 %>% 
  filter(Primary == "-Pi") %>% 
  select(Index, Genotype, r) %>% 
  arrange(Genotype)
Adding missing grouping variables: `Strain`, `Primary`
tmp %>% group_by(Genotype) %>% summarize(mean = mean(r), sd = num(sd(r), digits = 3))

kruskal.test(as.double(r) ~ Genotype, data = tmp)

    Kruskal-Wallis rank sum test

data:  as.double(r) by Genotype
Kruskal-Wallis chi-squared = 9.6092, df = 2, p-value = 0.008192
pairwise.wilcox.test(x = tmp$r, g = tmp$Genotype, paired = FALSE)

    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  tmp$r and tmp$Genotype 

           wildtype cta1::CTA1
cta1::CTA1 0.589    -         
cta1Δ      0.017    0.013     

P value adjustment method: holm 

survival rates with primary stress significantly different between cta1∆ vs either the wildtype or the complement, while no difference was detected between the latter two.

Primary stress enhanced in wildtype

Here, I first calculate the ASR score and its summary statistics. To determine if the effect is significant, I perform three types of tests: - T-test, most powerful but requiring the data to be normally distributed, which ours doesn’t. - Wilcoxson signed-rank test, paired - Wilcoxson rank-sum test (=Mann-Whitney’s U test), unpaired

In the paper, we report the P-values of the Wilcoxson signed-rank test

Comparison between r and r’, paired, signed-rank test.

tmp <- dat.f3s1 %>% 
  filter(Genotype == "wildtype") %>% 
  pivot_wider(id_cols = c(Index, Strain), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])
[1] "ASR_score mean = 23.90, 95% CI by bootstrap = [15.10, 36.20]"
with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))

    Paired t-test

data:  as.numeric(`-Pi`) and as.numeric(Mock)
t = 3.574, df = 5, p-value = 0.007988
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 0.08322759        Inf
sample estimates:
mean difference 
       0.190803 
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

    Wilcoxon signed rank exact test

data:  -Pi and Mock
V = 21, p-value = 0.01563
alternative hypothesis: true location shift is greater than 0

Primary stress enhanced in CTA1 complement

Comparison between r and r’, paired, signed-rank test.

tmp <- dat.f3s1 %>% 
  filter(Genotype == "cta1::CTA1") %>% 
  pivot_wider(id_cols = c(Index, Strain), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])
[1] "ASR_score mean = 15.39, 95% CI by bootstrap = [9.51, 21.90]"
with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))

    Paired t-test

data:  as.numeric(`-Pi`) and as.numeric(Mock)
t = 7.3528, df = 5, p-value = 0.0003652
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 0.1379887       Inf
sample estimates:
mean difference 
      0.1900807 
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

    Wilcoxon signed rank exact test

data:  -Pi and Mock
V = 21, p-value = 0.01563
alternative hypothesis: true location shift is greater than 0

Primary stress effect in cta1Δ

Paired, signed-rank test

tmp <- dat.f3s1 %>% 
  filter(Genotype == "cta1Δ") %>% 
  pivot_wider(id_cols = c(Index, Strain), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])
[1] "ASR_score mean = 5.14, 95% CI by bootstrap = [2.00, 10.47]"
with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))

    Paired t-test

data:  as.numeric(`-Pi`) and as.numeric(Mock)
t = 3.0595, df = 4, p-value = 0.01884
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 0.006144732         Inf
sample estimates:
mean difference 
     0.02026672 
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

    Wilcoxon signed rank exact test

data:  -Pi and Mock
V = 15, p-value = 0.03125
alternative hypothesis: true location shift is greater than 0

There is a statistically significant ASR effect in cta1∆, but the effect is very mild

Comparing the ASR effect in cta1Δ vs wild type

Unpaired, rank-sum test

tmp <- dat.f3s1 %>% 
  #filter(Genotype == "cta1Δ") %>% 
  pivot_wider(id_cols = c(Index, Strain, Genotype), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock) %>% 
  arrange(Genotype)

tmp %>% group_by(Genotype) %>% 
  summarize(ASR_score = paste(round(as.numeric(ASR),1), collapse = ", "), 
            mean = mean(ASR), sd = sd(ASR))

kruskal.test(as.numeric(ASR) ~ Genotype, data = tmp)

    Kruskal-Wallis rank sum test

data:  as.numeric(ASR) by Genotype
Kruskal-Wallis chi-squared = 7.4588, df = 2, p-value = 0.02401
pairwise.wilcox.test(x = as.numeric(tmp$ASR), g = tmp$Genotype, paired = FALSE, p.adjust.method = "none")

    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  as.numeric(tmp$ASR) and tmp$Genotype 

           wildtype cta1::CTA1
cta1::CTA1 0.240    -         
cta1Δ      0.017    0.052     

P value adjustment method: none 

The tests of interests among the pairwise comparisons are between the wild type and the other two strains Applying Bonferroni correction to the two tests, we conclude that cta1∆ is significantly different from the wild type in its ASR effect (P = 0.034), while the difference between cta1::CTA1 and wild type is not (P = 0.48).

60 v 80 v 2.5 mM

A second set of concentrations

dat.f3s2 <- dat.f3s %>% 
  mutate(Group = paste(Genotype, H2O2, sep = "_")) %>% 
  #filter(H2O2 %in% c("100 mM", "3 mM")) %>% 
  filter(Group %in% c("wt_60 mM", "Cgcta1::CgCTA1_80 mM", "cta1::URA3_2.5 mM")) %>% 
  select(-Group) %>% 
  mutate(
    Primary = factor(Primary, levels = c("M", "P"), 
                     labels = c("Mock", "-Pi")),
    Genotype = factor(Genotype, levels = c("wt", "Cgcta1::CgCTA1", "cta1::URA3"),
                      labels = c("wildtype", "cta1::CTA1", "cta1Δ")))
#write_tsv(dat.f3a, file = "../input/20230520-fig-3d-data-hb.tsv")

Plot

p <- dat.f3s2 %>% 
  mutate(Genotype = fct_recode(Genotype, "WT" = "wildtype")) %>% 
  ggplot(aes(x = Primary, y = r)) +
  geom_point(aes(shape = Primary), stroke = 1, size = 2,
             position = position_jitter(0.1)) +
  scale_shape_manual(name = "", values = c(1, 16), guide = "none") +
  #scale_fill_manual(name = bquote(H[2]*O[2]), values = c("white", "gray80")) +
  p.survival[-1] +
  facet_wrap(~Genotype + H2O2, nrow = 1) +
  panel_border(color = "black", size = 1.5) +
  theme(axis.line = element_blank(),
        axis.title.x = element_blank(), 
        strip.background = element_blank()
        )
p

ggsave("../output/20230806-fig3sup-asr-cta1-comp-2.png", width = 5, height = 3)

Statistical tests

Statistical test

  1. Determine if the basal survival rates are different between genotypes (Wilcoxon signed-rank test)
  2. Determine if the primary stress enhanced the survival in each genotype (Wilcoxon signed-rank test)

Basal survival rate

Between wt and cta1∆, unpaired, rank-sum test.

tmp <- dat.f3s2 %>% 
  filter(Primary == "Mock") %>% 
  select(Index, Genotype, r) %>% 
  mutate(r = as.double(r)) %>% 
  arrange(Genotype)

tmp %>% group_by(Genotype) %>% summarize(mean = mean(r), sd = num(sd(r), digits = 3))

kruskal.test(r ~ Genotype, data = tmp)
pairwise.wilcox.test(x = tmp$r, g = tmp$Genotype)

basal survival rates not significantly different between genotypes at the chosen [H2O2]

Survival rate with the primary stress

Between genotypes, unpaired, rank-sum test.

tmp <- dat.f3s2 %>% 
  filter(Primary == "-Pi") %>% 
  select(Index, Genotype, r) %>% 
  arrange(Genotype)

tmp %>% group_by(Genotype) %>% summarize(mean = mean(r), sd = num(sd(r), digits = 3))

kruskal.test(as.double(r) ~ Genotype, data = tmp)
pairwise.wilcox.test(x = tmp$r, g = tmp$Genotype, paired = FALSE)

survival rates with primary stress significantly different between cta1∆ vs either the wildtype or the complement. No significant difference between the latter two.

Primary stress enhanced in wildtype

Comparison between r and r’, paired, signed-rank test.

tmp <- dat.f3s2 %>% 
  filter(Genotype == "wildtype") %>% 
  pivot_wider(id_cols = c(Index, Strain), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])

with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

Primary stress enhanced in CTA1 complement

Comparison between r and r’, paired, signed-rank test.

tmp <- dat.f3s2 %>% 
  filter(Genotype == "cta1::CTA1") %>% 
  pivot_wider(id_cols = c(Index, Strain), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])

with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

Primary stress effect in cta1Δ

Paired, signed-rank test

tmp <- dat.f3s2 %>% 
  filter(Genotype == "cta1Δ") %>% 
  pivot_wider(id_cols = c(Index, Strain), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])

with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

ASR effect not significant in cta1∆.

Comparing the ASR effect in cta1Δ vs wild type

Unpaired, rank-sum test

tmp <- dat.f3s2 %>% 
  #filter(Genotype == "cta1Δ") %>% 
  pivot_wider(id_cols = c(Index, Strain, Genotype), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock) %>% 
  arrange(Genotype)

tmp %>% group_by(Genotype) %>% 
  summarize(ASR_score = paste(round(as.numeric(ASR),1), collapse = ", "), 
            mean = mean(ASR), sd = sd(ASR))

kruskal.test(as.numeric(ASR) ~ Genotype, data = tmp)
pairwise.wilcox.test(x = as.numeric(tmp$ASR), g = tmp$Genotype, paired = FALSE, p.adjust.method = "none")

The tests of interests among the pairwise comparisons are between the wild type and the other two strains Applying Bonferroni correction to the two tests, we conclude that cta1∆ is significantly different from the wild type in its ASR effect (P = 0.0044), while the difference between cta1::CTA1 and wild type is not (P = 1).

Fig6: ASR in rim15∆ vs wt

Goal

Determine if Rim15 is part of the signaling network behind the ASR.

Rationale

Rim15 is the yeast homolog of the Greatwall kinase, regulating multiple downstream processes and is itself regulated by at least three major kinase complexes. This puts it at a crossroad of signal integration. One of the upstream kinases regulating Rim15 is TORC1, which we later found to be connected with the ASR.

Data

Species Strain Genotype H2O2
C. glabrata yH001, yH002 wildtype 80, 100 mM
C. glabrata yH609, yH610 rim15∆ 60, 80 mM

Eight replicates (at two [H2O2]), two each from 06/28, 06/29 and 07/13, plus one each from 07/02 and 07/04 of 2022. The data from 7/4 should be excluded because Jinye noted media contamination on that day.

Data reformatting

Reformat JY’s data into a tidy format. Note that the following data file contains the same information as in the raw object imported at the beginning of this rmarkdown. The file below, however, contains experimental notes, including 7/4/22 data having media contamination issues.

tmp <- read_tsv("../input/20230522-rim15-data-jy.tsv", col_types = cols(), comment = "#") %>% 
  mutate(Date = gsub("(\\d\\d)(\\d\\d)(\\d\\d)", "\\1/\\2/\\3", Date)) %>% 
  select(-`MO/MM_percent`, -`PO/PM_percent`)

# data sanity check, quick view
sapply(select(tmp, Date, Species, Strain, Genotype, Len_1, Len_2, H2O2), unique)
$Date
[1] "07/04/22" "07/02/22" "06/29/22" "06/28/22" "07/13/22"

$Species
[1] "Cg"

$Strain
[1] "yH001" "yH002" "yH609" "yH610"

$Genotype
[1] "wt"     "rim15Δ"

$Len_1
[1] "45 min"

$Len_2
[1] "2 hr"

$H2O2
[1] "0 mM"   "80 mM"  "100 mM" "60 mM" 
dat.f6b <- tmp %>% 
  pivot_longer(c(Count_MO_MM, Count_PO_PM), names_to = "Primary", values_to = "Count") %>% 
  mutate(Primary = fct_recode(Primary, "Mock" = "Count_MO_MM", "-Pi" = "Count_PO_PM"),
         scaled = Count * Dilutions * 1e-3) %>% 
  group_by(Date, Strain, Genotype, Primary) %>%
  mutate(scaled_M = scaled[H2O2 == "0 mM"],
         r = scaled / scaled_M) %>%
  ungroup() %>% 
  select(Date, Species, Strain, Genotype, Primary, H2O2, Dilutions, 
         Count, scaled, scaled_M, r, Prism_data_point, Note) %>% 
  arrange(Date, Genotype, Primary)

Save the data for future references

write_tsv(dat.f6b, file = "../input/20230523-fig-6-data-hb.tsv")

Below the same data is extracted from the large dataset. The count information should be the same.

use.f6 <- paste0(c("06/28", "06/29", "07/02", "07/13"), "/22")
tmp <-  raw %>%
  filter(Date %in% use.f6) %>% 
  mutate(
    scaled = Count * Dilutions * 1e-2
  ) %>% 
  # remove uninformative columns. only one H2O2 conc used for each species
  select(-Len_1, -Len_2, -Experimenter)
# Assume the replicates were paired in the order they appear in the table,
# i.e., the first row in the MO, MM, PO, PM groups belong to the same biological 
# replicate, we can derive three ASR_scores for each date x species x Len_1

dat.f6 <- tmp %>% 
  # group by primary to calculate r (MO/MM) or r' (PO/PM)
  separate(Group, into = c("Primary", "Secondary"), sep = 1) %>% 
  group_by(Date, Strain, Primary) %>% 
  # calculate % survival
  mutate(scaled_M = scaled[Secondary == "M"],
         r = scaled / scaled[Secondary == "M"]) %>% 
  # remove the secondary mock as the information are all used
  filter(Secondary != "M")
dat.f6

Plot (all data)

Annotate the data. For 7/2 and 7/4 data, only use yH001 for the wt, so we end up with the same number of replicates for both strains.

dat.f6p <- dat.f6b %>% 
  filter(H2O2 != "0 mM", 
         !(Date == "07/02/22" & Strain == "yH002"), Date != "07/04/22") %>% 
  mutate(
    Genotype = factor(Genotype, levels = c("wt", "rim15Δ")),
    group = paste(Genotype, gsub(" ", "", H2O2), sep = "_"),
    Secondary = factor(group, 
                       levels = c("wt_100mM", "wt_80mM", "rim15Δ_80mM", "rim15Δ_60mM"),
                       labels = c("High", "Medium", "High", "Medium"))
  )
with(dat.f6p, table(Date, group))
          group
Date       rim15Δ_60mM rim15Δ_80mM wt_100mM wt_80mM
  06/28/22           4           4        4       4
  06/29/22           4           4        4       4
  07/02/22           2           2        2       2
  07/13/22           4           4        4       4
dat.f6p %>%
  ggplot(aes(x = H2O2, y = r)) + #p.survival[-3] +
  geom_point(aes(shape = Primary), stroke = 1, size = 2, 
             position = position_jitterdodge(jitter.width = 0.2, dodge.width = 0.9)) +
  stat_summary(aes(group = Primary), position = position_dodge(0.9),
               fun = mean, fun.max = mean, fun.min = mean,
               geom = "crossbar", color = "red", width = 0.5) +
  facet_wrap(~ Secondary + Genotype, nrow = 1, scales = "free_x") +
  scale_shape_manual(values = c("Mock" = 1, "-Pi" = 16)) +
  scale_y_continuous(labels = scales::percent) +
  xlab(bquote(H[2]*O[2]~(mM))) + ylab("% survival") +
  theme_bw(base_size = 14, base_line_size = 1) +
  panel_border(color = "black", size = 1) +
  theme(strip.text = element_text(size = rel(1), face = 3),
        strip.background = element_blank())

Basal survival rates

Statistical test for differences in basal survival between genotypes. I first applied the Kruskal-Wallis test, which is an extension of the Mann-Whitney’s U test for multiple groups and is equivalent to ANOVA but applied on ranks. I used this test to determine if there is evidence for differences in the basal survival rates among the four groups (2 genotypes x 2 [H2O2]).

tmp <- dat.f6p %>% filter(Primary == "Mock")
tmp %>% group_by(group) %>% 
  summarize(
    test = Hmisc::smean.cl.normal(r) %>% t() %>% as_tibble()
  ) %>% 
  unnest(test) %>% 
  mutate(across(where(is.double), round, digits = 3))
kruskal.test(r ~ group, data = tmp)

    Kruskal-Wallis rank sum test

data:  r by group
Kruskal-Wallis chi-squared = 15.726, df = 3, p-value = 0.00129

There are differences among the four groups. Inspecting the statistical summary, we can see that the high and low concentrations used for each genotype seem to match each other well. Therefore, we will next use A Wilcoxon rank-sum test to compare the two genotypes at either the high or the low dose

Statistical test for differences in basal survival between genotypes at 100 / 80 mM.

tmp <- dat.f6p %>% 
  filter(group %in% c("wt_100mM", "rim15Δ_80mM"), Primary == "Mock")
wilcox.test(r ~ group, data = tmp, paired = FALSE)

    Wilcoxon rank sum exact test

data:  r by group
W = 19, p-value = 0.535
alternative hypothesis: true location shift is not equal to 0

Statistical test for differences in basal survival between genotypes at 80/60 mM.

tmp <- dat.f6p %>% 
  filter(group %in% c("wt_80mM", "rim15Δ_60mM"), Primary == "Mock")
wilcox.test(r ~ group, data = tmp, paired = FALSE)

    Wilcoxon rank sum exact test

data:  r by group
W = 12, p-value = 0.1282
alternative hypothesis: true location shift is not equal to 0

yes, the survival rates are comparable between species at the two pairs of chosen [H2O2] We can conclude that there is no significant difference in survival when comparing 100 mM vs 80 mM for wt and rim15∆. Similarly, there is no significant difference in survival when 80 mM and 60 mM were used to treat the two strains, respectively.

100 vs 80 mM

Plot

dat.f6p %>% filter(Secondary == "High") %>% 
  mutate(Genotype = fct_recode(Genotype, `WT` = "wt")) %>% 
  ggplot(aes(x = Primary, y = r)) + 
  #geom_line(aes(group = paste0(Date, Strain, Secondary)),
  #          linetype = 2, linewidth = 0.1) + 
  geom_point(aes(shape = Primary), stroke = 1, size = 2,
             position = position_jitter(0.05)) +
  scale_shape_manual(values = c(1, 16), guide = "none") +
  p.survival[-1] +
  facet_wrap(~Genotype + H2O2, nrow = 1) +
  panel_border(color = "black", size = 1.5) +
  theme(axis.line = element_blank(),
        axis.title.x = element_blank(), 
        strip.background = element_blank(),
        legend.position = "top",
        legend.justification = "center",
        legend.text = element_text(size = rel(0.9)),
        legend.title = element_text(size = rel(0.9)))

#ggsave("../output/20230522-rim15-vs-wt-ASR.png", width = 3.6, height = 3.4)

Statistical test

  1. Determine if the basal survival rates are different between wt and cta1∆ (Wilcoxon signed-rank test)
  2. Determine if the primary stress enhanced the survival in each genotype (Wilcoxon signed-rank test)

Basal survival rate

Repeating the test above:

Statistical test for differences in basal survival between genotypes at 100 / 80 mM.

tmp <- dat.f6p %>% 
  filter(Secondary == "High", Primary == "Mock")
wilcox.test(r ~ Genotype, data = tmp, paired = FALSE)

    Wilcoxon rank sum exact test

data:  r by Genotype
W = 30, p-value = 0.535
alternative hypothesis: true location shift is not equal to 0

ASR in wildtype

Comparison between r and r’, paired, signed-rank test.

tmp <- dat.f6p %>% filter(Secondary == "High") %>%  
  filter(Genotype == "wt") %>% 
  pivot_wider(id_cols = c(Date, Strain, H2O2), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])
[1] "ASR_score mean = 6.29, 95% CI by bootstrap = [4.59, 8.59]"
with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))

    Paired t-test

data:  as.numeric(`-Pi`) and as.numeric(Mock)
t = 11.953, df = 6, p-value = 1.039e-05
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 0.1108889       Inf
sample estimates:
mean difference 
      0.1324153 
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

    Wilcoxon signed rank exact test

data:  -Pi and Mock
V = 28, p-value = 0.007813
alternative hypothesis: true location shift is greater than 0

ASR in rim15Δ

Paired, signed-rank test

tmp <- dat.f6p %>% filter(Secondary == "High") %>%
  filter(Genotype == "rim15Δ") %>% 
  pivot_wider(id_cols = c(Date, Strain, H2O2), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])
[1] "ASR_score mean = 3.45, 95% CI by bootstrap = [2.57, 4.33]"
with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))

    Paired t-test

data:  as.numeric(`-Pi`) and as.numeric(Mock)
t = 5.6886, df = 6, p-value = 0.0006367
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 0.03364967        Inf
sample estimates:
mean difference 
      0.0511075 
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

    Wilcoxon signed rank exact test

data:  -Pi and Mock
V = 28, p-value = 0.007813
alternative hypothesis: true location shift is greater than 0

ASR effect size between wt and rim15∆

tmp <- dat.f6p %>% 
  filter(Secondary == "High") %>% 
  pivot_wider(id_cols = c(Date, Strain, Genotype), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock) %>% 
  arrange(Genotype)

tmp %>% group_by(Genotype) %>% 
  summarize(ASR_score = paste(round(as.numeric(ASR),1), collapse = ", "), 
            mean = mean(ASR), sd = sd(ASR))

t.test(as.numeric(ASR) ~ Genotype, paired = FALSE, data = tmp)

    Welch Two Sample t-test

data:  as.numeric(ASR) by Genotype
t = 2.3448, df = 8.4269, p-value = 0.04551
alternative hypothesis: true difference in means between group wt and group rim15Δ is not equal to 0
95 percent confidence interval:
 0.07146653 5.61211996
sample estimates:
    mean in group wt mean in group rim15Δ 
            6.290364             3.448570 
wilcox.test(as.numeric(ASR) ~ Genotype, paired = FALSE, data = tmp)

    Wilcoxon rank sum exact test

data:  as.numeric(ASR) by Genotype
W = 41, p-value = 0.03788
alternative hypothesis: true location shift is not equal to 0

The difference in the ASR-score between rim15∆ and wild type is significant at a 0.05 level (P = 0.04).

Fig6-S1: RIM15 complementation

Goal

  • Validate that rim15∆ result is due to the intended deletion

Experiment

  • Bin constructed a RIM15 complementation strain by putting the gene’s CDS back to its endogenous locus.
  • Hanxi performed ASR to compare the ASR effect size of the complementation, the deletion and the wild type.

Data

Species Strain Genotype H2O2
C. glabrata yH001,002 wildtype 60, 80, 100 mM
C. glabrata yH609,610 rim51∆ 60, 80, 100 mM
C. glabrata yH731,732 rim15::RIM15 60, 80, 100 mM

Experiments between 8/8/23 - 8/10/23

Analysis

Read and format data

tmp <- read_tsv("../input/20230808-rim15-complement-data-ht.tsv",
                col_types = cols(), comment = "#") %>% 
  mutate(
    scaled = Count * Dilutions * 1e-2
  )

dat.f6s <- tmp %>% 
  # remove uninformative columns. only one H2O2 conc used for each species
  select(-Len_1, -Len_2, -Species) %>% 
  # group by experiment and H2O2 to calculate r (MO/MM) or r' (PO/PM)
  separate(Group, into = c("Primary", "Secondary"), sep = 1) %>% 
  group_by(Date, Strain, Primary) %>% 
  # calculate % survival
  mutate(scaled_M = scaled[Secondary == "M"],
         r = num(scaled / scaled[Secondary == "M"], digits = 3)) %>% 
  # remove the secondary mock as the information are all used
  filter(Secondary != "M") %>% 
  mutate(
    Primary = factor(Primary, levels = c("M", "P"), 
                     labels = c("Mock", "-Pi")),
    Genotype = factor(Genotype, levels = c("wt", "rim15::RIM15", "rim15::His3"),
                      labels = c("wildtype", "rim15::RIM15", "rim15Δ")),
    H2O2 = factor(H2O2, levels = c("60 mM", "80 mM", "100 mM"))
  )
dat.f6s

Plot (all data)

dat.f6s %>% 
  # leave out the lowest concentration in each group
  #filter(!H2O2 %in% c("2 mM", "60 mM")) %>% 
  ggplot(aes(x = H2O2, y = r)) + #p.survival[-3] +
  geom_point(aes(shape = Primary), stroke = 1, size = 2, 
             position = position_dodge(0.7)) +
  stat_summary(aes(group = Primary), position = position_dodge(0.7),
               fun = mean, fun.max = mean, fun.min = mean,
               geom = "crossbar", color = "red", width = 0.5) +
  facet_wrap(~ Genotype, nrow = 2, scales = "free_x") +
  scale_shape_manual(values = c("Mock" = 1, "-Pi" = 16)) +
  scale_y_continuous(labels = scales::percent) +
  xlab("Primary stress (45 min)") + ylab("% survival") +
  theme_bw(base_size = 14, base_line_size = 1) +
  panel_border(color = "black", size = 1) +
  theme(strip.text = element_text(size = rel(1), face = 3),
        strip.background = element_blank(),
        legend.position = c(0.6, 0.2),
        legend.background = element_blank())

100 mM vs 100 mM vs 80 mM

For this set, the same concentrations of H2O2 results in very similar basal survival rates. Here, we will test 60 mM for all three.

dat.f6s1 <- dat.f6s %>% 
  mutate(Group = paste(Genotype, H2O2, sep = "_")) %>% 
  filter(Group %in% c("wildtype_100 mM", "rim15Δ_80 mM", "rim15::RIM15_100 mM"))
#write_tsv(dat.f3a, file = "../input/20230520-fig-3d-data-hb.tsv")

Plot

p <- dat.f6s1 %>% 
  mutate(Genotype = fct_recode(Genotype, "WT" = "wildtype")) %>% 
  ggplot(aes(x = Primary, y = r)) +
  geom_point(aes(shape = Primary), stroke = 1, size = 2,
             position = position_jitter(0.1)) +
  scale_shape_manual(name = "", values = c(1, 16), guide = "none") +
  #scale_fill_manual(name = bquote(H[2]*O[2]), values = c("white", "gray80")) +
  p.survival[-1] +
  facet_wrap(~Genotype + H2O2, nrow = 1) +
  panel_border(color = "black", size = 1.5) +
  theme(axis.line = element_blank(),
        axis.title.x = element_blank(), 
        strip.background = element_blank()
        )
p


#ggsave("../output/20230818-fig6sup-asr-rim15-comp-1.png", width = 5, height = 3)

Statistical test

  1. Determine if the basal survival rates are different between genotypes (Wilcoxon signed-rank test)
  2. Determine if the primary stress enhanced the survival in each genotype (Wilcoxon signed-rank test)

Basal survival rate

Because we have three groups here, my strategy is to first perform an ANOVA-like, but rank-based, Krusal-Wallis test, where the null hypothesis is that all three groups’ distribution has the same “location” (=mean). I also performed a pairwise Wilcoxson rank sum test, although that is not necessary if the first test is deemed insignificant.

tmp <- dat.f6s1 %>% 
  filter(Primary == "Mock") %>% 
  select(Date, Genotype, r) %>% 
  mutate(r = as.double(r)) %>% 
  arrange(Genotype)
Adding missing grouping variables: `Strain`, `Primary`
tmp %>% group_by(Genotype) %>% summarize(mean = mean(r), sd = num(sd(r), digits = 3))

kruskal.test(r ~ Genotype, data = tmp)

    Kruskal-Wallis rank sum test

data:  r by Genotype
Kruskal-Wallis chi-squared = 2.6082, df = 2, p-value = 0.2714
pairwise.wilcox.test(x = tmp$r, g = tmp$Genotype)

    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  tmp$r and tmp$Genotype 

             wildtype rim15::RIM15
rim15::RIM15 0.54     -           
rim15Δ       0.82     0.54        

P value adjustment method: holm 

basal survival rates not significantly different between genotypes at the chosen [H2O2], as shown by both the (ANOVA-equivalent, rank-based) Kruskal-Wallis test and the (t-test equivalent) pairwise Wilcoxson rank-sum test (unpaired). P-values from the latter were adjusted for multiple comparison using Holm’s method (uniformly more powerful than Bonferroni)

Survival rate with the primary stress

Same strategy as above

tmp <- dat.f6s1 %>% 
  filter(Primary == "-Pi") %>% 
  select(Date, Genotype, r) %>% 
  arrange(Genotype)
Adding missing grouping variables: `Strain`, `Primary`
tmp %>% group_by(Genotype) %>% summarize(mean = mean(r), sd = num(sd(r), digits = 3))

kruskal.test(as.double(r) ~ Genotype, data = tmp)

    Kruskal-Wallis rank sum test

data:  as.double(r) by Genotype
Kruskal-Wallis chi-squared = 5.1345, df = 2, p-value =
0.07675
pairwise.wilcox.test(x = tmp$r, g = tmp$Genotype, paired = FALSE)

    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  tmp$r and tmp$Genotype 

             wildtype rim15::RIM15
rim15::RIM15 0.48     -           
rim15Δ       0.12     0.26        

P value adjustment method: holm 

survival rates with primary stress are lower in rim15∆ than either the wildtype or the complement, but the difference is not significant

Primary stress enhanced in wildtype

Here, I first calculate the ASR score and its summary statistics. To determine if the effect is significant, I perform three types of tests: - T-test, most powerful but requiring the data to be normally distributed, which ours doesn’t. - Wilcoxson signed-rank test, paired - Wilcoxson rank-sum test (=Mann-Whitney’s U test), unpaired

In the paper, we report the P-values of the Wilcoxson signed-rank test

Comparison between r and r’, paired, signed-rank test.

tmp <- dat.f6s1 %>% 
  filter(Genotype == "wildtype") %>% 
  pivot_wider(id_cols = c(Date, Strain), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])
[1] "ASR_score mean = 9.51, 95% CI by bootstrap = [5.31, 16.87]"
with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))

    Paired t-test

data:  as.numeric(`-Pi`) and as.numeric(Mock)
t = 6.4489, df = 5, p-value = 0.0006668
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 0.1402953       Inf
sample estimates:
mean difference 
      0.2040558 
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

    Wilcoxon signed rank exact test

data:  -Pi and Mock
V = 21, p-value = 0.01563
alternative hypothesis: true location shift is greater than 0

Primary stress enhanced in RIM15 complement

Comparison between r and r’, paired, signed-rank test.

tmp <- dat.f6s1 %>% 
  filter(Genotype == "rim15::RIM15") %>% 
  pivot_wider(id_cols = c(Date, Strain), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])
[1] "ASR_score mean = 11.56, 95% CI by bootstrap = [8.86, 15.21]"
with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))

    Paired t-test

data:  as.numeric(`-Pi`) and as.numeric(Mock)
t = 6.1387, df = 5, p-value = 0.0008331
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 0.1232347       Inf
sample estimates:
mean difference 
      0.1834538 
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

    Wilcoxon signed rank exact test

data:  -Pi and Mock
V = 21, p-value = 0.01563
alternative hypothesis: true location shift is greater than 0

Primary stress effect in rim15Δ

Paired, signed-rank test

tmp <- dat.f6s1 %>% 
  filter(Genotype == "rim15Δ") %>% 
  pivot_wider(id_cols = c(Date, Strain), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])
[1] "ASR_score mean = 5.32, 95% CI by bootstrap = [3.55, 7.71]"
with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))

    Paired t-test

data:  as.numeric(`-Pi`) and as.numeric(Mock)
t = 9.8572, df = 5, p-value = 9.157e-05
alternative hypothesis: true mean difference is greater than 0
95 percent confidence interval:
 0.08289006        Inf
sample estimates:
mean difference 
      0.1041887 
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

    Wilcoxon signed rank exact test

data:  -Pi and Mock
V = 21, p-value = 0.01563
alternative hypothesis: true location shift is greater than 0

At this set of concentrations, all three strains showed significant ASR effects.

Comparing the ASR effect in rim15Δ,rim15::RIM15 and wild type

Unpaired, rank-sum test

tmp <- dat.f6s1 %>% 
  #filter(Genotype == "cta1Δ") %>% 
  pivot_wider(id_cols = c(Date, Strain, Genotype), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock) %>% 
  arrange(Genotype)

tmp %>% group_by(Genotype) %>% 
  summarize(ASR_score = paste(round(as.numeric(ASR),1), collapse = ", "), 
            mean = mean(ASR), sd = sd(ASR))

kruskal.test(as.numeric(ASR) ~ Genotype, data = tmp)

    Kruskal-Wallis rank sum test

data:  as.numeric(ASR) by Genotype
Kruskal-Wallis chi-squared = 6.538, df = 2, p-value =
0.03804
pairwise.wilcox.test(x = as.numeric(tmp$ASR), g = tmp$Genotype, paired = FALSE, p.adjust.method = "holm")

    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  as.numeric(tmp$ASR) and tmp$Genotype 

             wildtype rim15::RIM15
rim15::RIM15 0.264    -           
rim15Δ       0.310    0.045       

P value adjustment method: holm 

The tests of interests among the pairwise comparisons are between the wild type and the other two strains Applying Bonferroni correction to the two tests, we conclude that rim15∆ is significantly different from the wild type in its ASR effect (P = 0.034), while the difference between cta1::CTA1 and wild type is not (P = 0.48).

80 mM vs 80 mM vs 60 mM

A second set of concentrations

dat.f6s2 <- dat.f6s %>% 
  mutate(Group = paste(Genotype, H2O2, sep = "_")) %>% 
  filter(Group %in% c("wildtype_80 mM", "rim15Δ_60 mM", "rim15::RIM15_80 mM"))
#write_tsv(dat.f3a, file = "../input/20230520-fig-3d-data-hb.tsv")

Plot

p <- dat.f6s2 %>% 
  mutate(Genotype = fct_recode(Genotype, "WT" = "wildtype")) %>% 
  ggplot(aes(x = Primary, y = r)) +
  geom_point(aes(shape = Primary), stroke = 1, size = 2,
             position = position_jitter(0.1)) +
  scale_shape_manual(name = "", values = c(1, 16), guide = "none") +
  #scale_fill_manual(name = bquote(H[2]*O[2]), values = c("white", "gray80")) +
  p.survival[-1] +
  facet_wrap(~Genotype + H2O2, nrow = 1) +
  panel_border(color = "black", size = 1.5) +
  theme(axis.line = element_blank(),
        axis.title.x = element_blank(), 
        strip.background = element_blank()
        )
p

ggsave("../output/20230818-fig6sup-asr-rim15-comp-2.png", width = 5, height = 3)

Statistical tests

Statistical test

  1. Determine if the basal survival rates are different between genotypes (Wilcoxon signed-rank test)
  2. Determine if the primary stress enhanced the survival in each genotype (Wilcoxon signed-rank test)

Basal survival rate

Between wt and cta1∆, unpaired, rank-sum test.

tmp <- dat.f6s2 %>% 
  filter(Primary == "Mock") %>% 
  select(Date, Genotype, r) %>% 
  mutate(r = as.double(r)) %>% 
  arrange(Genotype)

tmp %>% group_by(Genotype) %>% summarize(mean = mean(r), sd = num(sd(r), digits = 3))

kruskal.test(r ~ Genotype, data = tmp)
pairwise.wilcox.test(x = tmp$r, g = tmp$Genotype)

basal survival rates not significantly different between genotypes at the chosen [H2O2]

Survival rate with the primary stress

Between genotypes, unpaired, rank-sum test.

tmp <- dat.f6s2 %>% 
  filter(Primary == "-Pi") %>% 
  select(Date, Genotype, r) %>% 
  arrange(Genotype)

tmp %>% group_by(Genotype) %>% summarize(mean = mean(r), sd = num(sd(r), digits = 3))

kruskal.test(as.double(r) ~ Genotype, data = tmp)
pairwise.wilcox.test(x = tmp$r, g = tmp$Genotype, paired = FALSE)

survival rates with primary stress is lower in rim15∆ than in the wild type or the complement strain. The difference is approaching statistical significance at a 0.05 level by Kruskal-Wallis rank sum test.

Primary stress enhanced in wildtype

Comparison between r and r’, paired, signed-rank test.

tmp <- dat.f6s2 %>% 
  filter(Genotype == "wildtype") %>% 
  pivot_wider(id_cols = c(Date, Strain), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])

with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

Primary stress enhanced in RIM15 complement

Comparison between r and r’, paired, signed-rank test.

tmp <- dat.f6s2 %>% 
  filter(Genotype == "rim15::RIM15") %>% 
  pivot_wider(id_cols = c(Date, Strain), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])

with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

Primary stress effect in rim15Δ

Paired, signed-rank test

tmp <- dat.f6s2 %>% 
  filter(Genotype == "rim15Δ") %>% 
  pivot_wider(id_cols = c(Date, Strain), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock)

tmp

x <- Hmisc::smean.cl.boot(tmp$ASR)
sprintf("ASR_score mean = %.2f, 95%% CI by bootstrap = [%.2f, %.2f]", x[1], x[2], x[3])

with(tmp, t.test(as.numeric(`-Pi`), as.numeric(Mock), paired = TRUE, alternative = "g"))
with(tmp, wilcox.test(`-Pi`, Mock, paired = TRUE, alternative = "g"))

ASR effect not significant in cta1∆.

Comparing the ASR effect in rim15Δ,rim15::RIM15 and wild type

Unpaired, rank-sum test

tmp <- dat.f6s2 %>% 
  #filter(Genotype == "cta1Δ") %>% 
  pivot_wider(id_cols = c(Date, Strain, Genotype), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock) %>% 
  arrange(Genotype)

tmp %>% group_by(Genotype) %>% 
  summarize(ASR_score = paste(round(as.numeric(ASR),1), collapse = ", "), 
            mean = mean(ASR), sd = sd(ASR))

kruskal.test(as.numeric(ASR) ~ Genotype, data = tmp)
pairwise.wilcox.test(x = as.numeric(tmp$ASR), g = tmp$Genotype, paired = FALSE, p.adjust.method = "none")

Fig7_1: ASR in wt with rapamycin

Goal

Test the hypothesis that direct inhibition of TORC1 can provide ASR in C. glabrata. We will also test S. cerevisiae to determine if the negative regulation by TORC1 on stress response genes behind the ASR is conserved.

Rationale

If TORC1 inhibition by phosphate limitation directly contributes to the ASR, we should be able to mimic the effect by artificially inhibiting TORC1 with the drug rapamycin. The prediction is that rapamycin treatment should induce Cta1-GFP and provide ASR.

Data

Species Rapamycin (ng/mL) H2O2 Description
C. glabrata 50, 62.5, 125, 150 60 mM full ASR experiment
S. cerevisiae 50, 62.5, 125, 150 6 mM full ASR experiment
Date Species Rapa (ng/mL) H2O2 Strain
01/12/23 Cg 62.5, 125 60 mM yH181
01/18/23 Cg 62.5, 125 60 mM yH181
01/21/23 Sc 62.5, 125 4, 6 mM yH154
01/21/23 Cg 62.5, 125 40, 60 mM yH181
01/25/23 Sc 62.5, 125 4, 6 mM yH154
01/25/23 Cg 62.5, 125 40, 60 mM yH181
01/26/23 Sc 62.5, 125 4, 6 mM yH154
01/26/23 Cg 62.5, 125 40, 60 mM yH181
01/31/23 Sc 62.5, 125 4, 6 mM yH154
01/31/23 Cg 62.5, 125 40, 60 mM yH181
02/02/23 Cg 62.5, 125 40, 60 mM yH181

Note

Jinye used lower H2O2 concentration compared with preivous ASR experiments (100 mM for Cg and 10 mM for Sc) because the primary stresses tested here, i.e., rapamycin and nitrogen starvation, reduced survival while phosphate starvation used in previous ASR experiments didn’t. In order to maintain a similar CFU at the end, a lower H2O2 concentration was applied.

tmp <- read_csv("../input/20230205-Sc-Cg-rapamycin-nitrogen-ASR-raw.csv", col_types = cols(), comment = "#") %>% 
  mutate(Date = gsub("d(\\d\\d)(\\d\\d)(\\d\\d)", "\\1/\\2/\\3", Date))

dat.f7a <- tmp %>% 
  rename(Primary = `1st_Stress`) %>% 
  group_by(Date, Strain, Primary) %>% 
  mutate(
    scaled = Dilutions * Count * 1e-2,
    r = scaled / scaled[H2O2 == "Mock"]
  ) %>% 
  # confirmed that my calculation (r) equals JY's MO/MM and PO/PM
  # preserve her ASR_Score calculation for now
  select(-`MO/MM`, -`PO/PM`, -ASR_Score, ASR_Score)

# data sanity check, quick view
sapply(select(dat.f7a, Species, Strain, Genotype), unique)
Adding missing grouping variables: `Date`, `Primary`
$Date
[1] "02/02/23" "01/31/23" "01/26/23" "01/25/23" "01/21/23"
[6] "01/18/23" "01/12/23"

$Primary
[1] "Mock" "62.5" "125"  "0Ni" 

$Species
[1] "Cg" "Sc"

$Strain
[1] "yH181" "yH154"

$Genotype
[1] "wt"

Plotting

Effect of primary stress (Rapamycin and -N) on survival

Jinye mentioned that unlike phosphate starvation, rapamycin and nitrogen starvation reduce survival by themselves. To see this myself, I’m plotting the CFU after just the primary

tmp <- dat.f7a %>% 
  filter(H2O2 == "Mock") %>% 
  group_by(Date, Species) %>% 
  mutate(
    # arbitrarily decide any CFU counts < 3 are not included due to high CV
    Count = ifelse(Count < 3, NA, Count),
    scaled = Count * Dilutions * 1e-2,
    r = scaled / scaled[Primary == "Mock"]
  ) %>% 
  ungroup() %>% 
  filter(Primary != "Mock") %>% 
  select(Date, Species, Strain, Primary, Count, r)

dat.prim <-  raw %>%
  separate(Group, into = c("Primary", "Secondary"), sep = 1) %>% 
  # use the S2 dataset to examine the effect of phosphate starvation on survival
  filter(Date %in% use.s1b, Secondary == "M") %>% 
  mutate(
    # arbitrarily decide any CFU counts < 3 are not included due to high CV
    Count = ifelse(Count < 3, NA, Count),
    scaled = Count * Dilutions * 1e-2
  ) %>% 
  group_by(Date, Strain) %>% 
  # calculate r and r'
  mutate(r = scaled / scaled[Primary == "M"]) %>% 
  ungroup() %>% filter(Primary != "M") %>% 
  select(Date, Species, Strain, Primary, Count, r) %>% 
  bind_rows(tmp) %>% 
  mutate(Primary = factor(Primary,
                          levels = c("P", "62.5", "125", "0Ni"),
                          labels = c("-Pi", "Rapa\n62.5", 
                                     "Rapa\n125", "-Nitrogen")))
ggplot(dat.prim, aes(x = Primary, y = r)) + p.asr +
  scale_y_continuous(breaks = seq(0.2, 1.2, by = 0.2), labels = scales::percent) +
  xlab("Primary stress (45 min)") + ylab("Survival %")

#ggsave("../output/20230211-primary-stress-effect-on-survival.png")

Statistical tests

Use the nest-map-unnest workflow

dat.prim %>% 
  select(Species, Primary, r) %>% 
  nest(data = r) %>% 
  mutate(
    test = map(data, ~ t.test(.x, mu = 1, alternative = "two")),
    tidied = map(test, tidy)
  ) %>% 
  unnest(tidied) %>% 
  select(Species, Primary, mean_r = estimate, p.value, conf.low, conf.high, alternative) %>% 
  mutate(P.adj = p.adjust(p.value, method = "BH"),
         across(where(is.numeric), round, digits = 3)) %>% 
  arrange(Species, Primary)

Calibrate secondary stress strength

Jinye used two sets of H2O2 concentrations in this experiment, i.e., 40/4 mM and 60/6 mM for C. glabrata and S. cerevisiae, respectively.

with(dat.f7a, table(Date, paste(Species, H2O2, sep = ":")))
          
Date       Cg:40mM Cg:60mM Cg:Mock Sc:4mM Sc:6mM Sc:Mock
  01/12/23       0       3       3      0      0       0
  01/18/23       0       3       3      0      0       0
  01/21/23       4       4       4      4      4       4
  01/25/23       4       4       4      4      4       4
  01/26/23       4       4       4      4      4       4
  01/31/23       4       4       4      4      4       4
  02/02/23       4       4       4      0      0       0

First, we will test if the survival under these H2O2 concentrations are comparable across species, by analyzing the basal survival rate r

Statistical test for differences in basal survival between species at 60 or 6 mM. A Wilcoxon signed-rank test is used here since the two groups are dependent (=grouped) by the day of the experiment. One replicate was run per day. Using a paired-test ensures that day-to-day variation is accounted for.

tmp <- dat.f7a %>% 
  filter(H2O2 %in% c("60mM", "6mM"), Group == "MO", 
         !(Date %in% c("01/12/23", "01/18/23", "02/02/23")))# %>% 
tmp %>% group_by(Species) %>% summarize(mean = mean(r))
wilcox.test(r ~ Species, data = tmp, paired = TRUE)

    Wilcoxon signed rank exact test

data:  r by Species
V = 3, p-value = 0.625
alternative hypothesis: true location shift is not equal to 0

Statistical test for differences in basal survival between species at 40 or 4 mM.

tmp <- dat.f7a %>% 
  filter(H2O2 %in% c("40mM", "4mM"), Group == "MO", !(Date %in% c("02/02/23")))
tmp %>% group_by(Species) %>% summarize(mean = mean(r))
wilcox.test(r ~ Species, data = tmp, paired = TRUE)

    Wilcoxon signed rank exact test

data:  r by Species
V = 1, p-value = 0.25
alternative hypothesis: true location shift is not equal to 0

yes, the survival rates are comparable between species at the two pairs of chosen [H2O2]

Statistical test for differences in basal survival between the high and low H2O2 concentrations (60/6 vs 40/4 mM), species combined.

tmp <- filter(dat.f7a, Group == "MO") %>% 
  mutate(secondary = factor(H2O2, levels = c("60mM", "6mM", "40mM", "4mM"),
                            labels = c("high", "high", "low", "low")))
tmp %>% 
  group_by(secondary, Species) %>% 
  summarize(mean = num(mean(r), digits = 3), .groups = "drop")
wilcox.test(r ~ secondary, data = tmp, paired = FALSE)

    Wilcoxon rank sum exact test

data:  r by secondary
W = 21, p-value = 0.03103
alternative hypothesis: true location shift is not equal to 0
anova(lm(r ~ Species + secondary, data = tmp))
Analysis of Variance Table

Response: r
          Df    Sum Sq   Mean Sq F value  Pr(>F)  
Species    1 0.0006071 0.0006071  0.3490 0.56246  
secondary  1 0.0078300 0.0078300  4.5011 0.04887 *
Residuals 17 0.0295725 0.0017396                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

We can conclude that there is no significant difference in survival when comparing 40 mM vs 4 mM for C. glabrata vs S. cerevisiae. Similarly, there is no significant difference in survival when 60 mM and 6 mM were used to treat the two species, respectively. However, the survival rate is significantly lower under the higher set of concentrations (60 and 6 mM) compared with the lower ones (40 and 4 mM)

Rapamycin ASR

We will focus on 60/6 mM data for plotting and statistical analyses.

# we will not use the days of experiments where only one species was assayed
dat.7ap <- dat.f7a %>% 
  mutate(
    Secondary =  factor(H2O2, levels = c("40mM", "4mM", "60mM", "6mM"),
                        labels = c("40/4mM", "40/4mM", "60/6mM", "60/6mM"))
  ) %>% 
  filter(H2O2 != "Mock", Primary %in% c("125", "Mock")) %>% 
  mutate(Primary = factor(Primary, levels = c("Mock", "125")))

my calculation is the same as JY’s

with(dat.7ap, sum(round(rP/r, 5) != round(ASR_Score, 5)))

Plot

dat.7ap %>% filter(Secondary == "60/6mM") %>% 
  mutate(Primary = recode(Primary, "125" = "125 ng/mL")) %>% 
  ggplot(aes(x = Primary, y = r)) + p.survival[-1] +
  geom_line(aes(group = paste0(Date, Secondary)), linetype = 2, linewidth = 0.3) + 
  geom_point(shape = 1, stroke = 1, size = 1) +
  #labs(y = "% survival") + 
  theme(axis.title.x = element_blank(), strip.background = element_blank())

#ggsave("../output/20230520-rapamycin-ASR.png", width = 4.5, height = 2.2)

Statistical test

Summary statistics

dat.7as <- dat.7ap %>% 
  group_by(Date, Species, Strain, H2O2) %>% 
  mutate(rM = r[Primary == "Mock"], asr = r/rM) %>%
  filter(Primary != "Mock") %>% 
  rename(rP = "r", r = "rM") %>% 
  relocate(c(r, asr), .after = "rP") %>% 
  ungroup()

dat.7as %>% select(-Genotype, -Group, -Dilutions, -Count, -scaled) %>% 
  mutate(across(where(is.double), round, digits = 2))
dat.7as %>% 
  group_by(Secondary, Species) %>% 
  summarize(
    # smean.cl.boot returns a named vector. t() %>% as_tibble() turns it
    # into a one-row tibble, stored as a list column. unnest() then flattens
    # the list-column back out into regular columns
    test = Hmisc::smean.cl.boot(ASR_Score) %>% t() %>% as_tibble()
  ) %>% 
  unnest(test) %>% 
  mutate(across(where(is.numeric), round, digits = 2))
`summarise()` has grouped output by 'Secondary'. You can override using the `.groups` argument.

Wilcoxon signed-rank test comparing r’ and r (paired data)

dat.7as %>% 
  select(Species, Secondary, r, rP) %>% 
  nest(data = c(r, rP)) %>% 
  mutate(
    test = map(data, ~ wilcox.test(.x$rP, .x$r, paired = TRUE, alternative = "g")),
    tidied = map(test, tidy)
  ) %>% 
  unnest(tidied) %>% 
  select(Species, Secondary, T = statistic, p.value, alternative) %>% 
  mutate(p.bonf = p.adjust(p.value, method = "bonf"),
         p.holm = p.adjust(p.value, method = "holm"),
         p.hoch = p.adjust(p.value, method = "hoch"),
         across(starts_with("p."), round, digits = 5))

Paired t-tests comparing r’ and r

dat.7as %>% 
  select(Species, Secondary, r, rP) %>% 
  nest(data = c(r, rP)) %>% 
  mutate(
    test = map(data, ~ t.test(.x$rP, .x$r, paired = TRUE, alternative = "g")),
    tidied = map(test, tidy)
  ) %>% 
  unnest(tidied) %>% 
  select(Species, Secondary, p.value, alternative) %>% 
  mutate(P.adj = p.adjust(p.value, method = "BH"),
         across(where(is.numeric), round, digits = 3))

In conclusion, we found significant ASR effect at 125 ng/mL rapamycin treatment in C. glabrata using either a Wilcoxon signed-rank test (nonparametric) or a paired t test, both using a 0.05 rejection threhold. The same test approached the 0.05 significance threshold in S. cerevisiae

Fig7_2: ASR in Sch9-3E mutant

Goal

Test if Sch9-3E mutant results in reduced ASR.

Rationale

It is known in S. cerevisiae that TORC1-inhibition leads to the derepression of Msn2/4-mediated stress response via the TORC1-Sch9-Rim15 pathway. Specifically, Sch9 is a key proximal effector of TORC1, which phosphorylates the former. Phosphorylated Sch9 then phosphorylates Rim15, causing it to be retained in the cytoplasm and unable to activate Msn2/4 in the nucleus. Jinye created a phosphomimetic mutant of Sch9 (aka Sch9-3E) that is predicted to be constitutively active with respect to TORC1 signaling. Therefore, this mutant is expected to always repress the Rim15-Msn4 downstream effectors even when TORC1 itself is inhibited.

Data

Species Genotype H2O2
C. glabrata sch9::SCH9-wt-Nat 0, 20, 40, 60, 80, 100 mM
C. glabrata sch9::SCH9-3E-Nat 0, 20, 40, 60, 80, 100 mM

ASR experiments were repeated four times for the two strains on four consecutive days, from 05/14-05/17 of 2023.

Read in data

Reformat JY’s data into a tidy format

tmp <- read_csv("../input/20230515-CgSCH9-3E-data-jy.csv", col_types = cols(), comment = "#") %>% 
  mutate(Date = gsub("d(\\d\\d)(\\d\\d)(\\d\\d)", "\\1/\\2/\\3", Date),
         H2O2 = gsub("mM", " mM", H2O2),
         Len_1 = recode(Len_1, `2hr` = "2 hr", `45min` = "45 min"),
         Len_2 = recode(Len_2, `2hr` = "2 hr")) %>% 
  select(-`MO/MM_percent`, -`PO/PM_percent`)

# data sanity check, quick view
sapply(select(tmp, Species, Strain, Genotype, Len_1, Len_2, H2O2), unique)
$Species
[1] "Cg"

$Strain
[1] "yH692" "yH699" "yH693" "yH694" "yH695"

$Genotype
[1] "sch9_Nat_wt" "sch9_3E_Nat"

$Len_1
[1] "45 min"

$Len_2
[1] "2 hr"

$H2O2
[1] "Mock"   "20 mM"  "40 mM"  "60 mM"  "80 mM"  "100 mM"
dat.f7b <- tmp %>% 
  pivot_longer(c(Count_MO_MM, Count_PO_PM), names_to = "Primary", values_to = "Count") %>% 
  mutate(Primary = fct_recode(Primary, "Mock" = "Count_MO_MM", "-Pi" = "Count_PO_PM"),
         Genotype = fct_recode(Genotype,
                               `sch9::Sch9-3E-NAT` = "sch9_3E_Nat",
                               `sch9::Sch9-WT-NAT` = "sch9_Nat_wt"),
         scaled = Count * Dilutions * 1e-3) %>% 
  group_by(Date, Strain, Genotype, Primary) %>% 
  mutate(r = num(scaled / scaled[H2O2 == "Mock"], digits = 3)) %>% 
  select(Date, Species, Strain, Genotype, Primary, H2O2, Dilutions, Count, scaled, r) %>% 
  arrange(Date, Genotype, Primary)

Write the table to a file for future references

Calibrate secondary stress strength

Jinye tested a series of H2O2 concentrations in this experiment, i.e., 20, 40, 60, 80 and 100 mM. The goal here is to visualize the survival rates between the two genotypes and decide which pair to use for ASR comparisons.

dat.f7b %>% 
  filter(Primary == "Mock", H2O2 != "Mock") %>% 
  mutate(H2O2 = gsub(" mM", "", H2O2),
         H2O2 = factor(H2O2) %>% fct_reorder(as.numeric(H2O2))) %>% 
  ggplot(aes(x = H2O2, y = r, group = Genotype)) + 
  geom_bar(aes(fill = Genotype), stat = "summary", fun = "mean",
           position = position_dodge(0.9)) +
  geom_point(position = position_dodge(0.9), size = 1, color = "gray30") +
  scale_fill_brewer(palette = "Set2", direction = -1) +
  xlab(bquote(H[2]*O[2]~(mM))) + ylab("Survival rate") +
  theme_cowplot()

Somewhat to my surprise, the constitutively active Sch9-3E allele resulted in better survival without primary stress

For our purpose, let’s compare 40 mM and 60 mM for the wt to 100 mM for the Sch9-3E mutant.

A Wilcoxon signed-rank test is used here since the two groups are dependent (=grouped) by the day of the experiment. One replicate was run per day. Using a paired-test ensures that day-to-day variation is accounted for.

x1 = filter(dat.f7b, Genotype == "sch9::Sch9-WT-NAT", H2O2 == "40 mM") %>% pull(r) %>% as.double()
x2 = filter(dat.f7b, Genotype == "sch9::Sch9-WT-NAT", H2O2 == "60 mM") %>% pull(r) %>% as.double()
y = filter(dat.f7b, Genotype == "sch9::Sch9-3E-NAT", H2O2 == "100 mM") %>% pull(r) %>% as.double()
cbind("wt 40mM" = x1, "wt 60mM" = x2, "3E 100mM" = y)
        wt 40mM     wt 60mM   3E 100mM
[1,] 0.26621835 0.202531646 0.24174174
[2,] 0.40914634 0.362195122 0.17598684
[3,] 0.24153298 0.182263815 0.17717087
[4,] 0.38329646 0.342920354 0.17822384
[5,] 0.05391121 0.043868922 0.11525974
[6,] 0.19563197 0.095724907 0.10425532
[7,] 0.02770936 0.004310345 0.08857616
[8,] 0.15099715 0.064814815 0.11287879
cat("\n")
# Wilcoxon signed-rank tests
cat("<wt 40mM> vs <wt 60mM>")
<wt 40mM> vs <wt 60mM>
wilcox.test(x1, x2, paired = TRUE)

    Wilcoxon signed rank exact test

data:  x1 and x2
V = 36, p-value = 0.007813
alternative hypothesis: true location shift is not equal to 0
cat("<wt 40mM> vs <3E 100mM>")
<wt 40mM> vs <3E 100mM>
wilcox.test(x1, y, paired = TRUE)

    Wilcoxon signed rank exact test

data:  x1 and y
V = 29, p-value = 0.1484
alternative hypothesis: true location shift is not equal to 0
cat("<wt 60mM> vs <3E 100mM>")
<wt 60mM> vs <3E 100mM>
wilcox.test(x2, y, paired = TRUE)

    Wilcoxon signed rank exact test

data:  x2 and y
V = 16, p-value = 0.8438
alternative hypothesis: true location shift is not equal to 0
cat("\n")
# paired t-test
cat("<wt 40mM> vs <wt 80mM>")
<wt 40mM> vs <wt 80mM>
t.test(x1, x2, paired = TRUE)

    Paired t-test

data:  x1 and x2
t = 5.0382, df = 7, p-value = 0.001499
alternative hypothesis: true mean difference is not equal to 0
95 percent confidence interval:
 0.02851081 0.07894267
sample estimates:
mean difference 
     0.05372674 
cat("<wt 40mM> vs <3E 100mM>")
<wt 40mM> vs <3E 100mM>
t.test(x1, y, paired = TRUE)

    Paired t-test

data:  x1 and y
t = 1.7377, df = 7, p-value = 0.1258
alternative hypothesis: true mean difference is not equal to 0
95 percent confidence interval:
 -0.02409797  0.15768560
sample estimates:
mean difference 
     0.06679381 
cat("<wt 60mM> vs <3E 100mM>")
<wt 60mM> vs <3E 100mM>
t.test(x2, y, paired = TRUE)

    Paired t-test

data:  x2 and y
t = 0.35337, df = 7, p-value = 0.7342
alternative hypothesis: true mean difference is not equal to 0
95 percent confidence interval:
 -0.07437387  0.10050802
sample estimates:
mean difference 
     0.01306708 

For the wt strain, 40 mM clearly resulted in better survival than 60 mM, as expected. When comparing between wt and 3E mutant, 40 mM for wt and 100 mM for 3E have mean survival rates that are closer. Paired statistical tests yield P-values greater than 0.1 for both the 40mM and 60mM of wt compared with 100mM for the 3E mutant.

EDA: dat-to-day variation

From the plot for the basal survival rate above, there appears to be a lot of day-to-day variation. Here we visualize this variation more clearly

dat.f7b %>% 
  filter(H2O2 != "Mock") %>% 
  mutate(H2O2 = gsub(" mM", "", H2O2),
         H2O2 = factor(H2O2) %>% fct_reorder(as.numeric(H2O2))) %>% 
  ggplot(aes(x = H2O2, y = r)) + 
  geom_point(aes(color = Genotype, shape = Date, group = Genotype), 
             size = 2, position = position_dodge(.5)) + 
  xlab(bquote(H[2]*O[2]~(mM))) + ylab("Survival rate") +
  scale_color_brewer(palette = "Set2", direction = -1) +
  facet_wrap(~Primary, nrow = 2) + theme_cowplot() +
  background_grid(major = "y")

ASR-score comparison

We will subset the data to include the 40 mM and 60 mM for WT and 100 mM for 3E

dat.7bp <- ungroup(dat.f7b) %>% 
  filter(H2O2 != "Mock") %>% 
  mutate(
    H2O2 = gsub(" mM", "", H2O2),
    H2O2 = factor(H2O2) %>% fct_reorder(as.numeric(H2O2)),
    group = paste(str_sub(Genotype, 12, 13), H2O2, sep = "_")
  ) %>% 
  filter(H2O2 != "Mock", group %in% c("3E_100", "WT_60", "WT_40")) %>% 
  select(-Dilutions, -Count, -Species)

dat.7bs <- dat.7bp %>%
  group_by(Date, Strain, Genotype, H2O2) %>% # form groups to apply the same MO/MM
  mutate(
    rM = r[Primary == "Mock"], # MO/MM for each group
    ASR_Score = r/rM
  ) %>% ungroup() %>%
  rename(rP = "r", r = "rM") %>% 
  filter(Primary != "Mock") %>% 
  relocate(c(r, ASR_Score), .after = "rP")

Plot

Main comparison will be between wt_40 and 3E_100

Statistical test

Summary statistics

dat.7bs %>% 
  #filter(secondary == "60/6mM") %>% 
  group_by(Genotype, group) %>% 
  summarize(
    # smean.cl.boot returns a named vector. t() %>% as_tibble() turns it
    # into a one-row tibble, stored as a list column. unnest() then flattens
    # the list-column back out into regular columns
    test = Hmisc::smean.cl.boot(as.double(ASR_Score)) %>% t() %>% as_tibble()
  ) %>% 
  unnest(test) %>% 
  mutate(across(where(is.numeric), round, digits = 2))
`summarise()` has grouped output by 'Genotype'. You can override using the `.groups` argument.

Wilcoxon signed-rank test comparing r’ and r (paired data)

dat.7bs %>% 
  select(Genotype, group, r, rP) %>% 
  nest(data = c(r, rP)) %>% 
  mutate(
    test = map(data, ~ wilcox.test(.x$rP, .x$r, paired = TRUE, alternative = "g")),
    tidied = map(test, tidy)
  ) %>% 
  unnest(tidied) %>% 
  select(Genotype, group, T = statistic, p.value, alternative) %>% 
  mutate(p.bonf = p.adjust(p.value, method = "bonf"),
         p.holm = p.adjust(p.value, method = "holm"),
         p.hoch = p.adjust(p.value, method = "hoch"),
         across(starts_with("p."), round, digits = 5))

Paired t-tests comparing r’ and r

dat.7bs %>% 
  #filter(primary != "0Ni") %>% 
  select(Genotype, group, r, rP) %>% 
  nest(data = c(r, rP)) %>% 
  mutate(
    test = map(data, ~ t.test(.x$rP, .x$r, paired = TRUE, alternative = "g")),
    tidied = map(test, tidy)
  ) %>% 
  unnest(tidied) %>% 
  select(Genotype, group, p.value, alternative) %>% 
  mutate(P.adj = p.adjust(p.value, method = "BH"),
         across(where(is.numeric), round, digits = 3))

In conclusion, we found significant ASR effect at 125 ng/mL rapamycin treatment in C. glabrata using either a Wilcoxon signed-rank test (nonparametric) or a paired t test, both using a 0.05 rejection threhold. We couldn’t reject the null hypothesis of no survival difference between rapamycin treated vs untreated samples for the 62.5 ng/mL concentration, and also not for the higher dose in S. cerevisiae

Response to reviewer: ASR in msn4∆ and skn7∆ vs wt

Goal

Determine if transcriptional factor (TF) msn4 and skn7 contribute to the ASR.

Rationale

Msn4 and Skn7 are stress responsive TFs regulating the Cta1-GFP induction during phosphate starvation. The reviewer is wondering if the loss of Msn4 or Skn7 affect the ASR for H2O2. To answer this quesion, Jinye performed the CFU assay for H2O2 ASR with a gradient of H2O2 concentrations for wt, msn4∆ and skn7∆.

Data

Species Strain Genotype H2O2
C. glabrata yH001, yH002 wildtype 6 0, 80, 100 mM
C. glabrata yH396, yH397 msn4∆ 2 0, 40, 60 mM
C. glabrata yH422, yH423 skn7∆ 1 0, 20, 30, 40 mM

Five replicates (at three [H2O2]) for wt and msn4∆, four replicates (at three [H2O2]) for skn7∆.

Read and Reformat Data

Jinye has reformatted her raw data and saved the output as a tsv. We will skip the code below and go straight to the reformatted version.

tmp1 <- read_tsv("../input/msn4orskn7_ko_ASR_raw.tsv", col_types = cols(), comment = "#") %>% 
  mutate(Date = gsub("(\\d\\d)(\\d\\d)(\\d\\d)", "\\1/\\2/\\3", Date)) %>% 
  mutate(H2O2 = recode(H2O2, 'Mock' = '0mM')) %>% 
  mutate(H2O2 = gsub("mM", " mM", H2O2)) %>% 
  select(-`MO/MM_percent`, -`PO/PM_percent`)

# data sanity check, quick view
sapply(select(tmp1, Date, Species, Strain, Genotype, Len_1, Len_2, H2O2), unique)

dat.sf <- tmp1 %>% 
  pivot_longer(c(Count_MO_MM, Count_PO_PM), names_to = "Primary", values_to = "Count") %>% 
  mutate(Primary = fct_recode(Primary, "Mock" = "Count_MO_MM", "-Pi" = "Count_PO_PM"),
         scaled = Count * Dilutions * 1e-3) %>% 
  group_by(Date, Strain, Genotype, Primary) %>%
  mutate(scaled_M = scaled[H2O2 == "0 mM"],
         r = scaled / scaled_M) %>%
  ungroup() %>% 
  select(Date, Species, Strain, Genotype, Primary, H2O2, Dilutions, 
         Count, scaled, scaled_M, r) %>% 
  arrange(Date, Genotype, Primary)
write_tsv(dat.sf, file = "../input/20230913-sf-data-JY.tsv")
dat.sf <- read_tsv("../input/20230913-sf-data-JY.tsv")
Rows: 112 Columns: 11── Column specification ────────────────────────────────────────────────────────
Delimiter: "\t"
chr (6): Date, Species, Strain, Genotype, Primary, H2O2
dbl (5): Dilutions, Count, scaled, scaled_M, r
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Plot (all data)

filter out the skn7Δ 40mM treatment group, because the [H2O2] is too high according to the spotting assay result.

dat.sfp <- dat.sf %>% 
  filter(H2O2 != "0 mM", !(H2O2 == "40 mM" & Genotype == "skn7Δ")) %>% 
  mutate(
    Genotype = factor(Genotype, levels = c("wt", "msn4Δ", "skn7Δ")),
    group = paste(Genotype, gsub(" ", "", H2O2), sep = "_"),
    Secondary = 
      factor(group, 
             levels = c("wt_100mM", "wt_80mM", "wt_60mM", "msn4Δ_60mM", 
                        "msn4Δ_40mM", "msn4Δ_20mM",
                        "skn7Δ_30mM", "skn7Δ_20mM", "skn7Δ_10mM"),
             labels = c("High", "Medium", "low", "High", "Medium",
                        "low", "Medium", "low", "bottom")),
    Primary = factor(Primary, levels = c("Mock", "-Pi"))
    
  )
with(dat.sfp, table(Date, group))
           group
Date        msn4Δ_20mM msn4Δ_40mM msn4Δ_60mM skn7Δ_10mM skn7Δ_20mM skn7Δ_30mM
  d09/04/23          2          2          2          0          0          0
  d09/05/23          2          2          2          2          2          0
  d09/06/23          2          2          2          2          2          2
  d09/07/23          2          2          2          2          2          2
  d09/08/23          2          2          2          2          2          2
           group
Date        wt_100mM wt_60mM wt_80mM
  d09/04/23        2       2       2
  d09/05/23        2       2       2
  d09/06/23        2       2       2
  d09/07/23        2       2       2
  d09/08/23        2       2       2

Plot the Medium group to include in the response letter

dat.sfp %>%
  filter(Secondary == "Medium") %>% 
  ggplot(aes(x = H2O2, y = r)) + #p.survival[-3] +
  geom_point(aes(shape = Primary), stroke = 1, size = 2, 
             position = position_jitterdodge(jitter.width = 0.2, dodge.width = 0.9)) +
  stat_summary(aes(group = Primary), position = position_dodge(0.9),
               fun = mean, fun.max = mean, fun.min = mean,
               geom = "crossbar", color = "red", width = 0.5) +
  facet_wrap(~ Genotype, nrow = 1, scales = "free_x") +
  scale_shape_manual(values = c("Mock" = 1, "-Pi" = 16)) +
  scale_y_continuous(labels = scales::percent) +
  xlab(bquote(H[2]*O[2]~(mM))) + ylab("% survival") +
  theme_bw(base_size = 14, base_line_size = 1) +
  panel_border(color = "black", size = 1) +
  theme(strip.text = element_text(size = rel(1), face = 3),
        strip.background = element_blank())
ggsave("../output/20230913-msn4-skn7-ASR.png", width = 5, height = 3)

Basal survival rates

Statistical test for differences in basal survival between genotypes. I first applied the Kruskal-Wallis test, which is an extension of the Mann-Whitney’s U test for multiple groups and is equivalent to ANOVA but applied on ranks. I used this test to determine if there is evidence for differences in the basal survival rates among the four groups (2 genotypes x 2 [H2O2]).

tmp <- dat.sfp %>% filter(Secondary == "Medium", Primary == "Mock")
tmp %>% group_by(group) %>% 
  summarize(
    test = Hmisc::smean.cl.normal(r) %>% t() %>% as_tibble()
  ) %>% 
  unnest(test) %>% 
  mutate(across(where(is.double), round, digits = 3))
kruskal.test(r ~ group, data = tmp)

    Kruskal-Wallis rank sum test

data:  r by group
Kruskal-Wallis chi-squared = 2.8835, df = 2, p-value = 0.2365

There are no significance differences in the basal survival rate in the Medium group across genotypes

Statistical test for ASR

Comparing the ASR effect in skn7Δ, msn4∆ and wild type using Kruskal-Wallis Rank Sum test.

tmp <- dat.sfp %>% 
  filter(Secondary == "Medium") %>% 
  pivot_wider(id_cols = c(Date, Strain, Genotype), names_from = Primary, values_from = r) %>% 
  mutate(ASR = `-Pi`/Mock) %>% 
  arrange(Genotype)

tmp %>% group_by(Genotype) %>% 
  summarize(ASR_score = paste(round(as.numeric(ASR),1), collapse = ", "), 
            mean = mean(ASR), sd = sd(ASR))

kruskal.test(as.numeric(ASR) ~ Genotype, data = tmp)

    Kruskal-Wallis rank sum test

data:  as.numeric(ASR) by Genotype
Kruskal-Wallis chi-squared = 2.3209, df = 2, p-value = 0.3133
pairwise.wilcox.test(x = as.numeric(tmp$ASR), g = tmp$Genotype, paired = FALSE, p.adjust.method = "holm")

    Pairwise comparisons using Wilcoxon rank sum exact test 

data:  as.numeric(tmp$ASR) and tmp$Genotype 

      wt   msn4Δ
msn4Δ 1.00 -    
skn7Δ 0.75 0.75 

P value adjustment method: holm 

There is no significant difference in ASR among the three genotypes

LS0tCnRpdGxlOiAiUGxvdCBBU1IgcGhlb250eXBpYyByZXN1bHRzIgphdXRob3I6IEJpbiBIZQpkYXRlOiAiMjAyMy0xLTEgKHVwZGF0ZWQgYHIgU3lzLkRhdGUoKWApIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRoZW1lOiBjZXJ1bGVhbgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRvY19kZXB0aDogNAogICAgY29kZV9mb2xkaW5nOiBoaWRlCi0tLQoKYGBge3Igc2V0dXAsIG1lc3NhZ2U9RkFMU0V9CnJlcXVpcmUodGlkeXZlcnNlKQpyZXF1aXJlKGNvd3Bsb3QpCnJlcXVpcmUoYnJvb20pCnNldC5zZWVkKDEyMzQ1KQpgYGAKCiMjIEludHJvZHVjdGlvbgojIyMgR29hbAoKUGxvdHRpbmcgQVNSIGRhdGEgZm9yIEZpZy4gMSwgUzEsIC4uLgoKIyMjIERhdGEKQSBsYXJnZSBzZXQgb2YgZGF0YSB3ZXJlIGNvbGxlY3RlZCBhbmQgb3JnYW5pemVkIGJ5IEpZIGFuZCBIQiBpbnRvIHR3byBmaWxlcywgYXMgc2hvd24gYmVsb3cuIExhdGVyLCB3ZSB3aWxsIGltcG9ydCBtb3JlIHJlY2VudCBkYXRhc2V0cy4gVGhlIGRhdGEgZm9ybWF0cyBhcmUgbm90IHRoZSBtb3N0IGNvbnNpc3RlbnQuIEhvd2V2ZXIsIHdlIGhhdmUgdHJpZWQgdG8gYW5ub3RhdGUgdGhlIGhlYWRlcnMgc28gYXMgdG8gbWFrZSB0aGUgb3V0cHV0IHVuZGVyc3RhbmRhYmxlLgoKUmVhZCBpbiBkYXRhCmBgYHtyfQp0bXAgPC0gcmVhZF90c3YoIi4uL2lucHV0LzIwMjIwNzI2LUFTUi1DRlUtcmF3LnRzdiIsIGNvbF90eXBlcyA9IGNvbHMoKSwgY29tbWVudCA9ICIjIikKcmF3IDwtIHJlYWRfY3N2KCIuLi9pbnB1dC8yMDIyMTIyNC1BU1ItQ0ZVLXJhdy5jc3YiLCBjb2xfdHlwZXMgPSBjb2xzKCksIGNvbW1lbnQgPSAiIyIpICU+JSAKICBtdXRhdGUoRGF0ZSA9IGdzdWIoImQoXFxkXFxkKShcXGRcXGQpKFxcZFxcZCkiLCAiXFwxL1xcMi9cXDMiLCBEYXRlKSwKICAgICAgICAgTGVuXzEgPSByZWNvZGUoTGVuXzEsIGAyaHJgID0gIjIgaHIiLCBgNDVtaW5gID0gIjQ1IG1pbiIpLAogICAgICAgICBMZW5fMiA9IHJlY29kZShMZW5fMiwgYDJocmAgPSAiMiBociIpKSAlPiUgCiAgc2VsZWN0KC1gTU8vTU1gLCAtYFBPL1BNYCkgJT4lIAogIGJpbmRfcm93cyhhZGRfY29sdW1uKHRtcCwgRXhwZXJpbWVudGVyID0gIkpMIikpCgojIGRhdGEgc2FuaXR5IGNoZWNrLCBxdWljayB2aWV3CnNhcHBseShzZWxlY3QocmF3LCBTcGVjaWVzLCBTdHJhaW4sIEdlbm90eXBlLCBMZW5fMSwgTGVuXzIsIEgyTzIpLCB1bmlxdWUpCmBgYAoKIyMjIENvbW1vbiBwbG90dGluZyBmdW5jdGlvbnMKCmBgYHtyfQpzcGVjaWVzLmxhYmVsIDwtIGMoU2MgPSAiUy4gY2VyZXZpc2lhZSIsIENnID0gIkMuIGdsYWJyYXRhIikKCnAuc3Vydml2YWwgPC0gbGlzdCgKICBnZW9tX3BvaW50KHNoYXBlID0gMSwgc3Ryb2tlID0gMSwgc2l6ZSA9IDIsIAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjE1KSksCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sIGZ1bi5tYXggPSBtZWFuLCBmdW4ubWluID0gbWVhbiwKICAgICAgICAgICAgICAgZ2VvbSA9ICJjcm9zc2JhciIsIGNvbG9yID0gInJlZCIsIHdpZHRoID0gMC41KSwKICBmYWNldF93cmFwKH5TcGVjaWVzLCBzY2FsZXMgPSAiZnJlZV94IiwgbGFiZWxsZXIgPSBhc19sYWJlbGxlcihzcGVjaWVzLmxhYmVsKSksCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCksCiAgeWxhYigiJSBzdXJ2aXZhbCIpLAogIHRoZW1lX2Nvd3Bsb3QobGluZV9zaXplID0gMC43LCBmb250X3NpemUgPSAxNCksCiAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDEpLCBmYWNlID0gMykpCikKCnAuYXNyIDwtIGxpc3QoCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMSwgbGluZXR5cGUgPSAyLCBjb2xvciA9ICJncmF5NTAiKSwKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4xKSwgc2l6ZSA9IDIpLAogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9ICJtZWFuX2NsX2Jvb3QiLCBnZW9tID0gInBvaW50cmFuZ2UiLCBjb2xvciA9ICJyZWQiLAogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHggPSAwLjIpKSwKICBmYWNldF93cmFwKH5TcGVjaWVzLCBzY2FsZXMgPSAiZnJlZV94IiwgbGFiZWxsZXIgPSBhc19sYWJlbGxlcihzcGVjaWVzLmxhYmVsKSksCiAgdGhlbWVfY293cGxvdChsaW5lX3NpemUgPSAwLjcpLAogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgxLjEpLCBmYWNlID0gMykpCikKYGBgCgoKIyMgRmlnMTogQVNSIGJldHdlZW4gc3BlY2llcwpfKipHb2FsKipfCgotIENvbXBhcmUgdGhlIEFTUiBlZmZlY3QgYmV0d2VlbiBfUy4gY2VyZXZpc2lhZV8gYW5kIF9DLiBnbGFicmF0YV8gYXQgMTAgbU0gYW5kIDEwMCBtTSBbSDJPMl0sIHJlc3BlY3RpdmVseS4KCl8qKkV4cGVyaW1lbnQqKl8KCkppbnllIGhhcyBwZXJmb3JtZWQgc2V2ZXJhbCBleHBlcmltZW50cyBhdCB0aGVzZSB0d28gY29uY2VudHJhdGlvbnMsIGFzIHNob3duIGJlbG93CmBgYHtyfQpyYXcgJT4lIAogIGZpbHRlcihHZW5vdHlwZSA9PSAid3QiLCBIMk8yICVpbiUgYygiMTBtTSIsICIxMCBtTSIsICIxMDBtTSIsICIxMDAgbU0iKSwKICAgICAgICAgTGVuXzEgPT0gIjQ1IG1pbiIsIEdyb3VwID09ICJQTyIpICU+JSAKICBtdXRhdGUoZ3JvdXAgPSBwYXN0ZShyZWNvZGUoU3RyYWluLCB5SDE1NCA9ICJTYyIsIHlIMDAxID0gIkNnMSIsIHlIMDAyID0gIkNnMiIpLCAKICAgICAgICAgICAgICAgICAgICAgICBnc3ViKCIgP21NIiwgIiIsIEgyTzIpLCBzZXAgPSAiXyIpKSAlPiUgCiAgY291bnQoRGF0ZSwgZ3JvdXApICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gZ3JvdXAsIHZhbHVlc19mcm9tID0gbikKYGBgCldlIHdpbGwgdXNlIHRoZSAwNS8zMC8yMCwgMDYvMDEvMjAgYW5kIDA2LzA0LzIwIGRhdGEsIHdoaWNoIHdlcmUgdGhyZWUgY29uc2VjdXRpdmUgcmVwbGljYXRlcyBtZWFudCB0byBjb21wYXJlIHRoZSBBU1IgdW5kZXIgLVBpIGJldHdlZW4gdGhlIHR3byBzcGVjaWVzLiBUaGUgb3RoZXIgZGF0YXNldHMgd2VyZSBwYXJ0IG9mIGFuIGV4cGVyaW1lbnQgd2l0aCBkaWZmZXJlbnQgcHVycG9zZXMuCgpfKipEYXRhKipfCgoqKk1haW4gZGF0YXNldCoqOiAKCkRhdGUgICAgICAgU3BlY2llcyAgIFJlcGxpY2F0ZQotLS0tLS0tLSAgIC0tLS0tLS0tICAtLS0tLS0tLS0tCjA1LzMwLzIwICAgU2MsIENnICAgIDEKMDYvMDEvMjAgICBTYywgQ2cgICAgMgowNi8wNC8yMCAgIFNjLCBDZyAgICAyCgoqKk5vdGUqKjogb25lIHJlcGxpY2F0ZSBmb3IgU2Mgb24gMDUvMzAvMjAgc2hvd2VkIG11Y2ggbG93ZXIgQ0ZVIG51bWJlcnMgdGhhbiB0aGUgb3RoZXIgcGxhdGVzLgpgYGB7cn0KZmlsdGVyKHJhdywgRGF0ZSA9PSAiMDUvMzAvMjAiLCBTcGVjaWVzID09ICJTYyIpCmBgYApKaW55ZSByZW1vdmVkIHRoZSBzZWNvbmQgcmVwbGljYXRlIGZvciBib3RoIFNjIGFuZCBDZyBmcm9tIGhlciBkb3duc3RyZWFtIGFuYWx5c2VzLgoKQmVsb3cgYXJlIHRoZSBmaWx0ZXJlZCBkYXRhOgoKYGBge3J9CnVzZS5mMSA8LSBwYXN0ZTAoYygiMDYvMDQiLCAiMDYvMDEiLCAiMDUvMzAiKSwgIi8yMCIpCnRtcCA8LSAgcmF3ICU+JQogIGZpbHRlcihEYXRlICVpbiUgdXNlLmYxKSAlPiUgCiAgbXV0YXRlKAogICAgc2NhbGVkID0gQ291bnQgKiBEaWx1dGlvbnMgKiAxZS0yCiAgKSAlPiUgCiAgIyByZW1vdmUgdW5pbmZvcm1hdGl2ZSBjb2x1bW5zLiBvbmx5IG9uZSBIMk8yIGNvbmMgdXNlZCBmb3IgZWFjaCBzcGVjaWVzCiAgc2VsZWN0KC1TdHJhaW4sIC1HZW5vdHlwZSwgLUgyTzIsIC1MZW5fMSwgLUxlbl8yLCAtRXhwZXJpbWVudGVyKQogIAojIEFzc3VtZSB0aGUgdHJpcGxpY2F0ZXMgd2VyZSBwYWlyZWQgaW4gdGhlIG9yZGVyIHRoZXkgYXBwZWFyIGluIHRoZSB0YWJsZSwKIyBpLmUuLCB0aGUgZmlyc3Qgcm93IGluIHRoZSBNTywgTU0sIFBPLCBQTSBncm91cHMgYmVsb25nIHRvIHRoZSBzYW1lIGJpb2xvZ2ljYWwgCiMgcmVwbGljYXRlLCB3ZSBjYW4gZGVyaXZlIHRocmVlIEFTUl9zY29yZXMgZm9yIGVhY2ggZGF0ZSB4IHNwZWNpZXMgeCBMZW5fMQoKZGF0LmYxIDwtIHRtcCAlPiUgCiAgZ3JvdXBfYnkoRGF0ZSwgU3BlY2llcywgR3JvdXApICU+JQogIG11dGF0ZShSZXBsID0gcm93X251bWJlcigpKSAlPiUgCiAgIyBncm91cCBieSBwcmltYXJ5IHRvIGNhbGN1bGF0ZSByIChNTy9NTSkgb3IgcicgKFBPL1BNKQogIHNlcGFyYXRlKEdyb3VwLCBpbnRvID0gYygiUHJpbWFyeSIsICJTZWNvbmRhcnkiKSwgc2VwID0gMSkgJT4lIAogIGdyb3VwX2J5KERhdGUsIFNwZWNpZXMsIFJlcGwsIFByaW1hcnkpICU+JSAKICAjIGNhbGN1bGF0ZSAlIHN1cnZpdmFsCiAgbXV0YXRlKAogICAgc2NhbGVkX00gPSBzY2FsZWRbU2Vjb25kYXJ5ID09ICJNIl0sCiAgICByID0gbnVtKHNjYWxlZCAvIHNjYWxlZFtTZWNvbmRhcnkgPT0gIk0iXSwgZGlnaXRzID0gMykKICApICU+JSAKICAjIHJlbW92ZSB0aGUgc2Vjb25kYXJ5IG1vY2sgYXMgdGhlIGluZm9ybWF0aW9uIGFyZSBhbGwgdXNlZAogIGZpbHRlcihTZWNvbmRhcnkgIT0gIk0iKSAlPiUgCiAgIyA1LzMwLzIwIHJlcGxpY2F0ZSAyIGlzIGV4Y2x1ZGVkCiAgZmlsdGVyKCEoRGF0ZSA9PSAiMDUvMzAvMjAiICYgUmVwbCA9PSAyKSkKZGF0LmYxCmBgYAoKXyoqUGxvdHRpbmcqKl8KCiMjIyMgUGxvdApgYGB7cn0KZGF0LmYxICU+JSAKICBtdXRhdGUoUHJpbWFyeSA9IHJlY29kZShQcmltYXJ5LCBNID0gIk1vY2siLCBQID0gIi1QaSIpLAogICAgICAgICBQcmltYXJ5ID0gZmFjdG9yKFByaW1hcnksIGxldmVscyA9IGMoIk1vY2siLCAiLVBpIikpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gUHJpbWFyeSwgeSA9IHIpKSArCiAgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBQcmltYXJ5KSwgc3Ryb2tlID0gMSwgc2l6ZSA9IDIsIAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIoMC4xKSkgKwogIHAuc3Vydml2YWxbLTFdICsKICBzY2FsZV9zaGFwZV9tYW51YWwobmFtZSA9ICIiLCB2YWx1ZXMgPSBjKDEsIDE2KSwKICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJyID0gTU8vTU0iLCAicicgPSBQTy9QTSIpKSArCiAgcGFuZWxfYm9yZGVyKGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuNSkgKwogIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSAiY2VudGVyIiwKICAgICAgICBsZWdlbmQuYm94Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAtMTAsIDAsICJwdCIpLAogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC45KSksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC45KSkpCiMgIHhsYWIoIlByaW1hcnkgc3RyZXNzICg0NSBtaW4pIikjICsgeWxhYigiJSBzdXJ2aXZhbCIpCgpnZ3NhdmUoIi4uL291dHB1dC8yMDIzMDIyOC1maWcxZC1hc3Itbm9QaS1jb21wYXJlLnBuZyIsIHdpZHRoID0gMy41LCBoZWlnaHQgPSAzKQpgYGAKCl8qKlN0YXRpc3RpY2FsIHRlc3RzKipfCgojIyMjIFN0YXRpc3RpY2FsIHRlc3RzCjEuIERldGVybWluZSBpZiB0aGUgYmFzYWwgc3Vydml2YWwgcmF0ZXMgYXJlIGRpZmZlcmVudCBiZXR3ZWVuIHNwZWNpZXMgKFdpbGNveG9uIHNpZ25lZC1yYW5rIHRlc3QpCjEuIERldGVybWluZSBpZiB0aGUgcHJpbWFyeSBzdHJlc3MgZW5oYW5jZWQgdGhlIHN1cnZpdmFsIGluIF9lYWNoXyBzcGVjaWVzIChXaWxjb3hvbiBzaWduZWQtcmFuayB0ZXN0KQoKX0Jhc2FsIHN1cnZpdmFsIHJhdGVfCgpUaGUgYmFzYWwgc3Vydml2YWwgcmF0ZXMgYmV0d2VlbiBzcGVjaWVzIHdpdGhpbiB0aGUgc2FtZSBkYXkgYXJlIG5vdCAicGFpcmVkIi4gV2Ugd2lsbCB1c2UgYSByYW5rLXN1bSB0ZXN0IGhlcmUuCmBgYHtyfQp0bXAgPC0gZGF0LmYxICU+JSAKICBmaWx0ZXIoUHJpbWFyeSA9PSAiTSIpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhEYXRlLCBSZXBsKSwgbmFtZXNfZnJvbSA9IFNwZWNpZXMsIHZhbHVlc19mcm9tID0gcikKdG1wCndpdGgodG1wLCB0LnRlc3QoYXMubnVtZXJpYyhDZyksIGFzLm51bWVyaWMoU2MpLCBwYWlyZWQgPSBGQUxTRSkpCgp3aXRoKHRtcCwgd2lsY294LnRlc3QoQ2csIFNjLCBwYWlyZWQgPSBGQUxTRSkpCmBgYAo+IGJhc2FsIHN1cnZpdmFsIHJhdGVzIGFyZSBub3Qgc2lnbmlmaWNhbnRseSBiZXR3ZWVuIHNwZWNpZXMKCl9QcmltYXJ5IHN0cmVzcyBlbmhhbmNlZCBzdXJ2aXZhbCAoQVNSKSBpbiBDZ18KClRoZSBjb21wYXJpc29uIGJldHdlZW4gciBhbmQgcicgaXMgcGFpcmVkLiBXZSB3aWxsIHVzZSBhIHNpZ25lZC1yYW5rIHRlc3QuCmBgYHtyfQp0bXAgPC0gZGF0LmYxICU+JSAKICBmaWx0ZXIoU3BlY2llcyA9PSAiQ2ciKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoRGF0ZSwgUmVwbCksIG5hbWVzX2Zyb20gPSBQcmltYXJ5LCB2YWx1ZXNfZnJvbSA9IHIpICU+JSAKICBtdXRhdGUoQVNSID0gUC9NKQp0bXAKCnggPC0gSG1pc2M6OnNtZWFuLmNsLmJvb3QodG1wJEFTUikKc3ByaW50ZigiQVNSX3Njb3JlIG1lYW4gPSAlLjJmLCA5NSUlIENJIGJ5IGJvb3RzdHJhcCA9IFslLjJmLCAlLjJmXSIsIHhbMV0sIHhbMl0sIHhbM10pCgp3aXRoKHRtcCwgdC50ZXN0KGFzLm51bWVyaWMoUCksIGFzLm51bWVyaWMoTSksIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKCndpdGgodG1wLCB3aWxjb3gudGVzdChQLCBNLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpCmBgYAoKX1ByaW1hcnkgc3RyZXNzIG5vIGVmZmVjdCBpbiBTY18KCmBgYHtyfQp0bXAgPC0gZGF0LmYxICU+JSAKICBmaWx0ZXIoU3BlY2llcyA9PSAiU2MiKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoRGF0ZSwgUmVwbCksIG5hbWVzX2Zyb20gPSBQcmltYXJ5LCB2YWx1ZXNfZnJvbSA9IHIpICU+JSAKICBtdXRhdGUoQVNSID0gUC9NKQoKdG1wCgp4IDwtIEhtaXNjOjpzbWVhbi5jbC5ib290KHRtcCRBU1IpCgpzcHJpbnRmKCJBU1Jfc2NvcmUgbWVhbiA9ICUuMmYsIDk1JSUgQ0kgYnkgYm9vdHN0cmFwID0gWyUuMmYsICUuMmZdIiwgeFsxXSwgeFsyXSwgeFszXSkKCndpdGgodG1wLCB0LnRlc3QoYXMubnVtZXJpYyhQKSwgYXMubnVtZXJpYyhNKSwgcGFpcmVkID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAiZyIpKQoKd2l0aCh0bXAsIHdpbGNveC50ZXN0KFAsIE0sIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKYGBgCgoKIyMgUzFBOiBCYXNhbCBIMk8yIHJlc2lzdGFuY2UKXyoqR29hbCoqXwoKLSBDb21wYXJlIHRoZSBiYXNhbCBzdXJ2aXZhbCByYXRlcyBvZiB0aGUgdHdvIHNwZWNpZXMgYXQgZGlmZmVyZW50IFtIMk8yXSB0byBpZGVudGlmeSBjb21wYXJhYmxlIGNvbmNlbnRyYXRpb25zIGZvciBBU1IuCgpfKipFeHBlcmltZW50KipfCgotIEppbnllIG1lYXN1cmVkIENGVSBmb3IgX1MuIGNlcmV2aXNpYWVfIGFuZCBfQy4gZ2xhYnJhdGFfIGV4cG9zZWQgdG8gYSByYW5nZSBvZiBbSDJPMl0KCl8qKkRhdGEqKl8KCi0gRmlsdGVyIHRoZSBkYXRhIGZvciB0aGUgcmVsZXZhbnQgZXhwZXJpbWVudHMuCgoqKk1haW4gZGF0YXNldCoqOiAKClNwZWNpZXMgICAgICAgICBIMk8yICAgICAgICAgICAgICAgICAgICAgICAgRGVzY3JpcHRpb24KLS0tLS0tLS0tLS0tLS0gIC0tLS0tLS0tLS0tLS0gICAgICAgICAgICAgICAtLS0tLS0tLS0tLS0tLS0KQy4gZ2xhYnJhdGEgICAgIDAsIDIwLCA0MCwgNjAsIDgwLCAxMDAgbU0gICBPbmx5IE0gYW5kIE8sIG5vIHByaW1hcnkgc3RyZXNzClMuIGNlcmV2aXNpYWUgICAwLCAyLCA0LCA2LCA4LCAxMCBtTSAgICAgICAgT25seSBNIGFuZCBPLCBubyBwcmltYXJ5IHN0cmVzcwoKRGF0ZSAgICAgICBTcGVjaWVzICAgUmVwbGljYXRlCi0tLS0tLS0tICAgLS0tLS0tLS0gIC0tLS0tLS0tLS0KMDMvMjEvMjIgICBTYywgQ2cgICAgMQowMy8yMi8yMiAgIFNjLCBDZyAgICAyCjAzLzI0LzIyICAgU2MsIENnICAgIDMKMDMvMjgvMjIgICBTYywgQ2cgICAgNAowNC8wMS8yMiAgIFNjLCBDZyAgICA1CgoKYGBge3J9CnVzZS5zMSA8LSBwYXN0ZTAoYygiMDMvMjEiLCAiMDMvMjIiLCAiMDMvMjQiLCAiMDMvMjgiLCAiMDQvMDEiKSwgIi8yMiIpCmRhdC5zMSA8LSByYXcgJT4lIHNlbGVjdCgtRXhwZXJpbWVudGVyLCAtTGVuXzEsIC1MZW5fMiwgLUdlbm90eXBlKSAlPiUgCiAgbXV0YXRlKHNjYWxlZCA9IENvdW50ICogRGlsdXRpb25zICogMWUtMykgJT4lIAogIGZpbHRlcihEYXRlICVpbiUgdXNlLnMxKSAlPiUgCiAgZ3JvdXBfYnkoRGF0ZSwgU3RyYWluKSAlPiUgCiAgbXV0YXRlKHIgPSBudW0oc2NhbGVkIC8gc2NhbGVkW0dyb3VwID09ICJNIl0sIGRpZ2l0cyA9IDMpKSAlPiUgCiAgc2VsZWN0KC1Hcm91cCkKZGF0LnMxCiN3cml0ZV90c3YoZGF0LnMxLCBmaWxlID0gIi4uL2lucHV0LzIwMjMwMzAyLWZpZy1zMWEtZGF0YS1oYi50c3YiKQpgYGAKIyMjIyBQbG90CgpgYGB7cn0KcCA8LSBkYXQuczEgJT4lIAogIG11dGF0ZShIMk8yID0gZ3N1YigiIG1NIiwgIiIsIEgyTzIpLAogICAgICAgICBIMk8yID0gZmN0X3Jlb3JkZXIoSDJPMiwgYXMubnVtZXJpYyhIMk8yKSkpICU+JSAKICBmaWx0ZXIoSDJPMiAhPSAiMCIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBIMk8yLCB5ID0gcikpICsKICBnZW9tX3BvaW50KGFlcyhzaGFwZSA9IERhdGUpKSArIAogICNnZW9tX2xpbmUoYWVzKGdyb3VwID0gRGF0ZSwgY29sb3IgPSBEYXRlKSwgYWxwaGEgPSAwLjgpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJEYXJrMiIpICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gMTo1LCBndWlkZSA9ICJub25lIikgKwogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9ICJtZWFuX2NsX2Jvb3QiLCBnZW9tID0gInBvaW50cmFuZ2UiLCBjb2xvciA9ICJyZWQyIiwKICAgICAgICAgICAgICAgc2l6ZSA9IDAuOCwgcG9zaXRpb24gPSBwb3NpdGlvbl9udWRnZSh4ID0gMC4zKSkgKwogIGZhY2V0X3dyYXAoflNwZWNpZXMsIHNjYWxlcyA9ICJmcmVlX3giLCBsYWJlbGxlciA9IGFzX2xhYmVsbGVyKHNwZWNpZXMubGFiZWwpKSArCiAgeGxhYihicXVvdGUoSFsyXSpPWzJdfihtTSkpKSArIHlsYWIoIkJhc2FsIHN1cnZpYWwgcmF0ZSAocikiKSArCiAgdGhlbWVfY293cGxvdChsaW5lX3NpemUgPSAwLjcpICsKICB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMSksIGZhY2UgPSAzKSkKcAojZ2dzYXZlKCIuLi9vdXRwdXQvMjAyMzAxMDEtYmFzYWwtc3Vydml2YWwtYWNyb3NzLWgybzItcmFuZ2Utc2MtY2cucG5nIiwgd2lkdGggPSA1LCBoZWlnaHQgPSAzKQpgYGAKCiMjIyMgU3RhdGlzdGljYWwgdGVzdHMKU3RhdGlzdGljYWwgdGVzdCBmb3IgZGlmZmVyZW5jZSBiZXR3ZWVuIHNwZWNpZXMgYXQgdGhlIGhpZ2hlc3QgY29uY2VudHJhdGlvbi4gVXNpbmcgdGhlIFdpbGNveG9uIHJhbmstc3VtIHRlc3QgKGFrYSBNYW5uLVdoaXRuZXkncyBVIHRlc3QpCmBgYHtyfQp0bXAgPC0gZGF0LnMxICU+JSAKICBmaWx0ZXIoSDJPMiAlaW4lIGMoIjEwMCBtTSIsICIxMCBtTSIpKQp0bXAgJT4lIGdyb3VwX2J5KFNwZWNpZXMpICU+JSBzdW1tYXJpemUobWVhbiA9IG1lYW4ocikpCgp3aWxjb3gudGVzdChyIH4gU3BlY2llcywgZGF0YSA9IHRtcCwgcGFpcmVkID0gRkFMU0UpCmBgYAo+IG5vIHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGF0IDEwIHZzIDEwMCBtTQoKIyMgUzFCOiBBU1IgYXQgZGlmZmVyZW50IEgyTzIKXyoqR29hbCoqXwoKLSBHZW5lcmFsaXplIHRoZSBtYWluIGZpZ3VyZSBmaW5kaW5nIG9mIGEgc3Ryb25nZXIgQVNSIGluIF9DLiBnbGFicmF0YV8gdGhhbiBpbiBfUy4gY2VyZXZpc2lhZV8gYXQgYSBzaW5nbGUgcHJpbWFyeSBzdHJlc3MgdHJlYXRtZW50IGxlbmd0aCBieSBleHRlbmRpbmcgdGhlIGFuYWx5c2lzIHRvIG11bHRpcGxlIGxlbmd0aCBvZiBwcmltYXJ5IHRyZWF0bWVudAoKXyoqRGF0YSoqXwoKKipNYWluIGRhdGFzZXQqKjogCgpTcGVjaWVzICAgICAgIEgyTzIgICAgICAgICAgICAgICAgICAgICAgIERlc2NyaXB0aW9uIAotLS0tLS0tLSAgICAgIC0tLS0tICAgICAgICAgICAgICAgICAgICAgIC0tLS0tLS0tLS0tLQpDLiBnbGFicmF0YSAgIDAsIDIwLCA0MCwgNjAsIDgwLCAxMDAgbU0gIGZ1bGwgQVNSIGV4cGVyaW1lbnQKUy4gY2VyZXZpc2lhZSAwLCAyLCA0LCA2LCA4LCAxMG1NICAgICAgICBmdWxsIEFTUiBleHBlcmltZW50CgpEYXRlICAgICAgIFNwZWNpZXMgICBTdHJhaW4gICAgUmVwbGljYXRlCi0tLS0tICAgICAgLS0tLS0tLS0gIC0tLS0tLS0gICAtLS0tLS0tLS0tCjA3LzE2LzIyICAgQ2cgICAgICAgIHlIMDAxLDIgICAgYTEKMDcvMTcvMjIgICBDZyAgICAgICAgeUgwMDEsMiAgICBhMgowNy8xOC8yMiAgIENnICAgICAgICB5SDAwMSwyICAgIGEzCjA3LzI5LzIyICAgQ2cgICAgICAgIHlIMDAxICAgICAgYjEKMDcvMjkvMjIgICBTYyAgICAgICAgeUgxNTQgICAgICBiMQowOC8wMS8yMiAgIENnICAgICAgICB5SDAwMSAgICAgIGIyCjA4LzAxLzIyICAgU2MgICAgICAgIHlIMTU0ICAgICAgYjIKMDgvMDIvMjIgICBDZyAgICAgICAgeUgwMDEgICAgICBiMwowOC8wMi8yMiAgIFNjICAgICAgICB5SDE1NCAgICAgIGIzCjA4LzA0LzIyICAgQ2cgICAgICAgIHlIMDAxICAgICAgYjQKMDgvMDQvMjIgICBTYyAgICAgICAgeUgxNTQgICAgICBiNAowOC8xMS8yMiAgIENnICAgICAgICB5SDAwMSAgICAgIGI1CjA4LzExLzIyICAgU2MgICAgICAgIHlIMTU0ICAgICAgYjUKCgpgYGB7cn0KdXNlLnMxYiA8LSBwYXN0ZTAoYygiMDcvMTYiLCAiMDcvMTciLCAiMDcvMTgiLCAiMDcvMjkiLCAiMDgvMDEiLCAiMDgvMDIiLCAiMDgvMDQiLCAiMDgvMTEiKSwgIi8yMiIpCmRhdC5zMWIgPC0gIHJhdyAlPiUKICBzZXBhcmF0ZShHcm91cCwgaW50byA9IGMoIlByaW1hcnkiLCAiU2Vjb25kYXJ5IiksIHNlcCA9IDEpICU+JSAKICBtdXRhdGUoCiAgICAjIGFyYml0cmFyaWx5IGRlY2lkZSBhbnkgQ0ZVIGNvdW50cyA8IDMgYXJlIG5vdCBpbmNsdWRlZCBkdWUgdG8gaGlnaCBDVgogICAgQ291bnQgPSBpZmVsc2UoQ291bnQgPCAzLCBOQSwgQ291bnQpLAogICAgc2NhbGVkID0gQ291bnQgKiBEaWx1dGlvbnMgKiAxZS0zCiAgKSAlPiUgCiAgZmlsdGVyKERhdGUgJWluJSB1c2UuczFiKSAlPiUgCiAgZ3JvdXBfYnkoRGF0ZSwgU3RyYWluLCBQcmltYXJ5KSAlPiUgCiAgIyBjYWxjdWxhdGUgciBhbmQgcicKICBtdXRhdGUociA9IG51bShzY2FsZWQgLyBzY2FsZWRbU2Vjb25kYXJ5ID09ICJNIl0sIGRpZ2l0cyA9IDMpKSAlPiUgCiAgIyByZW1vdmUgdGhlIHNlY29uZGFyeSBtb2NrIGFzIHRoZSBpbmZvcm1hdGlvbiBhcmUgYWxsIHVzZWQKICBmaWx0ZXIoU2Vjb25kYXJ5ICE9ICJNIikgJT4lCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoRGF0ZSwgU3RyYWluLCBTcGVjaWVzLCBIMk8yKSwgCiAgICAgICAgICAgICAgbmFtZXNfZnJvbSA9IFByaW1hcnksIHZhbHVlc19mcm9tID0gciwgbmFtZXNfcHJlZml4ID0gInIiKSAlPiUgCiAgbXV0YXRlKEFTUl9zY29yZSA9IHJQIC8gck0pCiAgCmRhdC5zMWIKI3dyaXRlX3RzdihkYXQuczFiLCBmaWxlID0gIi4uL2lucHV0LzIwMjMwMzAyLWZpZy1zMWItZGF0YS1oYi50c3YiKQpgYGAKIyMjIyBQbG90CgpgYGB7cn0KcCA8LSBkYXQuczFiICU+JSAKICBmaWx0ZXIoIWlzLm5hKEFTUl9zY29yZSkpICU+JSAKICBtdXRhdGUoSDJPMiA9IGdzdWIoIiA/bU0iLCAiIiwgSDJPMiksCiAgICAgICAgIEgyTzIgPSBmY3RfcmVvcmRlcihIMk8yLCBhcy5udW1lcmljKEgyTzIpKSkgJT4lIAogIGZpbHRlcihIMk8yICE9ICIwIikgJT4lIAogIGdncGxvdChhZXMoeCA9IEgyTzIsIHkgPSBBU1Jfc2NvcmUpKSArIHAuYXNyICsKICAjZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMSwgbGluZXR5cGUgPSAyLCBjb2xvciA9ICJncmF5NTAiKSArCiAgI2dlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjEpLCBhbHBoYSA9IDAuOCkgKyAKICAjc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gIm1lYW5fY2xfYm9vdCIsIGdlb20gPSAicG9pbnRyYW5nZSIsIGNvbG9yID0gInJlZCIsCiAgIyAgICAgICAgICAgICBzaXplID0gMC44LCBwb3NpdGlvbiA9IHBvc2l0aW9uX251ZGdlKHggPSAwLjIpKSArCiAgI3NjYWxlX3lfbG9nMTAoKSArCiAgI2ZhY2V0X3dyYXAoflNwZWNpZXMsIHNjYWxlcyA9ICJmcmVlX3giLCBsYWJlbGxlciA9IGFzX2xhYmVsbGVyKHNwZWNpZXMubGFiZWwpKSArCiAgeGxhYihicXVvdGUoSFsyXSpPWzJdfihtTSkpKSArIHlsYWIoIkFTUiBzY29yZSAocicvcikiKSMgKwogICN0aGVtZV9jb3dwbG90KGxpbmVfc2l6ZSA9IDAuNykgKwogICN0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMSksIGZhY2UgPSAzKSkKcAojZ2dzYXZlKCIuLi9vdXRwdXQvMjAyMzAxMDItQVNSLXNjb3JlLWFjcm9zcy1oMm8yLXJhbmdlLXNjLWNnLnBuZyIsIHdpZHRoID0gNSwgaGVpZ2h0ID0gMykKYGBgCgojIyMjIFN0YXRpc3RpY2FsIHN1bW1hcnkKCmBgYHtyfQpkYXQuczFiICU+JSAKICBmaWx0ZXIoIWlzLm5hKEFTUl9zY29yZSkpICU+JSAKICBtdXRhdGUoSDJPMiA9IGdzdWIoIiA/bU0iLCAiIiwgSDJPMiksCiAgICAgICAgIEgyTzIgPSBmY3RfcmVvcmRlcihIMk8yLCBhcy5udW1lcmljKEgyTzIpKSkgJT4lIAogIGZpbHRlcihIMk8yICE9ICIwIikgJT4lIAogIGdyb3VwX2J5KFNwZWNpZXMsIEgyTzIpICU+JSAKICBzdW1tYXJpc2Uock0gPSBtZWFuKHJNKSwgQVNSID0gbWVhbihBU1Jfc2NvcmUpLCBzZF9hc3IgPSBzZChBU1Jfc2NvcmUpKQpgYGAKCiMjIFMyOiBBU1IgYXQgZGlmZmVyZW50IHByaW1hcnkgc3RyZXNzIGR1cmF0aW9uCl8qKkdvYWwqKl8KCi0gR2VuZXJhbGl6ZSB0aGUgbWFpbiBmaWd1cmUgZmluZGluZyBvZiBhIHN0cm9uZ2VyIEFTUiBpbiBfQy4gZ2xhYnJhdGFfIHRoYW4gaW4gX1MuIGNlcmV2aXNpYWVfIGF0IGEgc2luZ2xlIFtIfjJ+T34yfl0gYnkgZXh0ZW5kaW5nIHRoZSBhbmFseXNpcyB0byBtdWx0aXBsZSBjb25jZW50cmF0aW9ucwoKXyoqRGF0YSoqXwoKKipNYWluIGRhdGFzZXQqKjogCgpTcGVjaWVzICAgICAgIExlbl9ub1BpICAgICAgICAgIEgyTzIgICAgICAgIERlc2NyaXB0aW9uIAotLS0tLS0tLSAgICAgIC0tLS0tLS0tLSAgICAgICAgIC0tLS0tLSAgICAgIC0tLS0tLS0tLS0tLQpDLiBnbGFicmF0YSAgIDQ1LCA5MCwgMTM1IG1pbiAgIDEwMCBtTSAgICAgIGZ1bGwgQVNSIGV4cGVyaW1lbnQKUy4gY2VyZXZpc2lhZSA0NSwgOTAsIDEzNSBtaW4gICAxMG1NICAgICAgICBmdWxsIEFTUiBleHBlcmltZW50CgpEYXRlICAgICAgIFNwZWNpZXMgICBMZW5fbm9QaSAgICBTdHJhaW4gCi0tLS0tICAgICAgLS0tLS0tLS0gIC0tLS0tLS0tLSAgIC0tLS0tLS0KMDYvMDYvMjAgICBDZyAgICAgICAgNDUgbWluICAgICAgeUgwMDEKMDYvMDYvMjAgICBTYyAgICAgICAgNDUgbWluICAgICAgeUgxNTQKMDYvMDYvMjAgICBDZyAgICAgICAgOTAgbWluICAgICAgeUgwMDEKMDYvMDYvMjAgICBTYyAgICAgICAgOTAgbWluICAgICAgeUgxNTQKMDYvMDYvMjAgICBDZyAgICAgICAgMTM1IG1pbiAgICAgeUgwMDEKMDYvMDYvMjAgICBTYyAgICAgICAgMTM1IG1pbiAgICAgeUgxNTQKCioqU3VwcG9ydGluZyBkYXRhc2V0Kio6IAoKRGF0ZSAgICAgICBTcGVjaWVzICAgTGVuX25vUGkgICAgU3RyYWluIAotLS0tLSAgICAgIC0tLS0tLS0tICAtLS0tLS0tLS0gICAtLS0tLS0tCjA1LzMwLzIyICAgQ2cgICAgICAgIDQ1IG1pbiAgICAgIHlIMDAxICAKMDUvMzAvMjIgICBTYyAgICAgICAgNDUgbWluICAgICAgeUgxNTQKMDYvMDEvMjIgICBDZyAgICAgICAgNDUgbWluICAgICAgeUgwMDEKMDYvMDEvMjIgICBTYyAgICAgICAgNDUgbWluICAgICAgeUgxNTQKMDYvMDQvMjIgICBDZyAgICAgICAgNDUgbWluICAgICAgeUgwMDEKMDYvMDQvMjIgICBTYyAgICAgICAgNDUgbWluICAgICAgeUgxNTQKCmBgYHtyfQp1c2UuczIgPC0gcGFzdGUwKGMoIjA2LzA2IiwgIjA2LzA0IiwgIjA2LzAxIiwgIjA1LzMwIiksICIvMjAiKQp0bXAgPC0gIHJhdyAlPiUKICBmaWx0ZXIoRGF0ZSAlaW4lIHVzZS5zMikgJT4lIAogIG11dGF0ZSgKICAgICMgYXJiaXRyYXJpbHkgZGVjaWRlIGFueSBDRlUgY291bnRzIDwgMyBhcmUgbm90IGluY2x1ZGVkIGR1ZSB0byBoaWdoIENWCiAgICAjIG5vdCBpbiB1c2UgaGVyZS4gaW5zdGVhZCwgbGFiZWwgdGhlbSBpbiB0aGUgcGxvdCAoc2VlIGJlbG93KQogICAgIyBjb3VudCA9IGlmZWxzZShDb3VudCA8IDMsIE5BLCBDb3VudCksCiAgICBzY2FsZWQgPSBDb3VudCAqIERpbHV0aW9ucyAqIDFlLTIKICApICU+JSAKICAjIHJlbW92ZSB1bmluZm9ybWF0aXZlIGNvbHVtbnMuIG9ubHkgb25lIEgyTzIgY29uYyB1c2VkIGZvciBlYWNoIHNwZWNpZXMKICBzZWxlY3QoLVN0cmFpbiwgLUdlbm90eXBlLCAtSDJPMiwgLUxlbl8yLCAtRXhwZXJpbWVudGVyKQpgYGAKICAKQXNzdW1lIHRoZSB0cmlwbGljYXRlcyB3ZXJlIHBhaXJlZCBpbiB0aGUgb3JkZXIgdGhleSBhcHBlYXIgaW4gdGhlIHRhYmxlLCBpLmUuLCB0aGUgZmlyc3Qgcm93IGluIHRoZSBNTywgTU0sIFBPLCBQTSBncm91cHMgYmVsb25nIHRvIHRoZSBzYW1lIGJpb2xvZ2ljYWwgcmVwbGljYXRlLCB3ZSBjYW4gZGVyaXZlIHRocmVlIEFTUl9zY29yZXMgZm9yIGVhY2ggZGF0ZSB4IHNwZWNpZXMgeCBMZW5fMQpgYGB7cn0KZGF0LnMyIDwtIHRtcCAlPiUgCiAgZ3JvdXBfYnkoRGF0ZSwgU3BlY2llcywgTGVuXzEsIEdyb3VwKSAlPiUKICBtdXRhdGUoUmVwbCA9IHJvd19udW1iZXIoKSkgJT4lIAogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKERhdGUsIFNwZWNpZXMsIExlbl8xLCBSZXBsKSwKICAgICAgICAgICAgICBuYW1lc19mcm9tID0gR3JvdXAsIHZhbHVlc19mcm9tID0gc2NhbGVkLCBuYW1lc19zZXAgPSAiIikgJT4lIAogIG11dGF0ZSgKICAgIHIgPSBNTy9NTSwgCiAgICBycCA9IFBPL1BNLCAKICAgIEFTUl9zY29yZSA9IHJwL3IsCiAgICBsb3dfY291bnQgPSBNTyA8IDEgIyBtYXJrIGV4cGVyaW1lbnRzIHdpdGggPCAzIGNvdW50cwogICkKZGF0LnMyCiN3cml0ZV90c3YoZGF0LnMyLCBmaWxlID0gIi4uL2lucHV0LzIwMjMwMzAyLWZpZy1zMi1kYXRhLWhiLnRzdiIpCmBgYAojIyMjIFBsb3QKYGBge3J9CnAgPC0gZGF0LnMyICU+JSAKICAjZmlsdGVyKCFpcy5uYShBU1Jfc2NvcmUpKSAlPiUgCiAgbXV0YXRlKGxlbl8xID0gZmFjdG9yKGdzdWIoIiA/bWluIiwgIiIsIExlbl8xKSwgbGV2ZWxzID0gYygiNDUiLCAiOTAiLCAiMTM1IikpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gbGVuXzEsIHkgPSBBU1Jfc2NvcmUpKSArIHAuYXNyICsKIyAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMSwgbGluZXR5cGUgPSAyLCBjb2xvciA9ICJncmF5NTAiKSArCiMgIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjEpLCBzaXplID0gMikgKyAKIyAgc3RhdF9zdW1tYXJ5KHBvc2l0aW9uID0gcG9zaXRpb25fbnVkZ2UoeCA9IDAuMiksCiMgICAgICAgICAgICAgICBmdW4uZGF0YSA9ICJtZWFuX2NsX2Jvb3QiLCBnZW9tID0gInBvaW50cmFuZ2UiLCBjb2xvciA9ICJyZWQiKSArCiAgeGxhYigiTGVuZ3RoIG9mIHByaW1hcnkgc3RyZXNzIChtaW4pIikgKyB5bGFiKCJBU1Igc2NvcmUgKHInL3IpIikgKwojICBmYWNldF93cmFwKH5TcGVjaWVzLCBzY2FsZXMgPSAiZnJlZV94IiwgbGFiZWxsZXIgPSBhc19sYWJlbGxlcihzcGVjaWVzLmxhYmVsKSkgKwojICB0aGVtZV9jb3dwbG90KGxpbmVfc2l6ZSA9IDAuNykgKwogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMSksIGZhY2UgPSAzKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuMSwgMC44NSksCiAgICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDEpLCBmYWNlID0gMykpCnAKI2dnc2F2ZSgiLi4vb3V0cHV0LzIwMjMwMTAzLUFTUi1zY29yZS1hY3Jvc3Mtbm9QaS1sZW5ndGgtc2MtY2cucG5nIiwgd2lkdGggPSA1LCBoZWlnaHQgPSAzKQpgYGAKCiMjIyMgU3RhdGlzdGljYWwgc3VtbWFyeSBhbmQgdGVzdApgYGB7cn0KZGF0LnMyICU+JSAKICAjZmlsdGVyKCFsb3dfY291bnQpICU+JSAKICBtdXRhdGUobGVuXzEgPSBmYWN0b3IoZ3N1YigiID9taW4iLCAiIiwgTGVuXzEpLCBsZXZlbHMgPSBjKCI0NSIsICI5MCIsICIxMzUiKSkpICU+JSAKICBncm91cF9ieShTcGVjaWVzLCBsZW5fMSkgJT4lIAogIHN1bW1hcml6ZShuID0gbigpLCBBU1IgPSBtZWFuKEFTUl9zY29yZSksIHNkX2FzciA9IHNkKEFTUl9zY29yZSksIC5ncm91cHMgPSAiZHJvcCIpICU+JSAKICBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLmRvdWJsZSksIG51bSwgc2lnZmlnID0gMykpCmBgYAoKQmVjYXVzZSBvZiB0aGUgc21hbGwgc2FtcGxlIHNpemUgKDMpIGZvciA5MCBhbmQgMTM1IG1pbnV0ZXMsIFdpbGNveG9uIHNpZ25lZC1yYW5rIHRlc3QgZG9lc24ndCBoYXZlIHBvd2VyIHRvIGRldGVjdCBzaWduaWZpY2FudCBkaWZmZXJlbmNlcyBhdCBhbnkgY29udmVudGlvbmFsIHNpemUgb2YgdGhlIHRlc3QgKGxvd2VyIHAtdmFsdWUgZm9yIGEgc2FtcGxlIHNpemUgMyBpcyAwLjI1KS4gVXNpbmcgdC10ZXN0IGJlbG93LCBrbm93aW5nIHRoYXQgdGhlIG5vcm1hbCBhc3N1bXB0aW9uIGlzIGxpa2VseSBub3QgbWV0LiBPdmVyYWxsLCB3ZSBzaG91bGQgZm9jdXMgb24gdGhlIHRyZW5kIGFuZCBub3QgdGhlIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZSBpbiB0aGlzIHJlc3VsdC4KYGBge3J9CmRhdC5zMiAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBtdXRhdGUobGVuXzEgPSBmYWN0b3IoZ3N1YigiID9taW4iLCAiIiwgTGVuXzEpLCBsZXZlbHMgPSBjKCI0NSIsICI5MCIsICIxMzUiKSkpICU+JSAKICBzZWxlY3QoU3BlY2llcywgbGVuXzEsIHIsIHJwKSAlPiUgCiAgbmVzdChkYXRhID0gYyhyLCBycCkpICU+JSAKICBtdXRhdGUoCiAgICB0ZXN0ID0gbWFwKGRhdGEsIH4gdC50ZXN0KC54JHJwLCAueCRyLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpLAogICAgdGlkaWVkID0gbWFwKHRlc3QsIHRpZHkpCiAgKSAlPiUgCiAgdW5uZXN0KHRpZGllZCkgJT4lIAogIHNlbGVjdChTcGVjaWVzLCBsZW5fMSwgcC52YWx1ZSwgbWV0aG9kLCBhbHRlcm5hdGl2ZSkgJT4lIAogIG11dGF0ZShwLmJvbmYgPSBwLmFkanVzdChwLnZhbHVlLCBtZXRob2QgPSAiYm9uZiIpLAogICAgICAgICBwLmhvbG0gPSBwLmFkanVzdChwLnZhbHVlLCBtZXRob2QgPSAiaG9sbSIpLAogICAgICAgICBwLmhvY2ggPSBwLmFkanVzdChwLnZhbHVlLCBtZXRob2QgPSAiaG9jaCIpLAogICAgICAgICBhY3Jvc3Moc3RhcnRzX3dpdGgoInAuIiksIHJvdW5kLCBkaWdpdHMgPSA1KSkgJT4lIAogIGFycmFuZ2UoU3BlY2llcywgbGVuXzEpCmBgYAoKCmBgYHtyfQpwIDwtIGRhdC5zMiAlPiUgCiAgI2ZpbHRlcighaXMubmEoQVNSX3Njb3JlKSkgJT4lIAogIG11dGF0ZShsZW5fMSA9IGZhY3RvcihMZW5fMSwgbGV2ZWxzID0gYygiNDUgbWluIiwgIjkwIG1pbiIsICIxMzUgbWluIikpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gU3BlY2llcywgeSA9IEFTUl9zY29yZSkpICsKICBnZW9tX3BvaW50KCNhZXMoZmlsbCA9IGxvd19jb3VudCksCiAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcigwLjEpLCBzaXplID0gMS41LCBzaGFwZSA9IDIxKSArIAogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9ICJtZWFuX3NlIiwgZ2VvbSA9ICJwb2ludHJhbmdlIiwgY29sb3IgPSAicmVkIikgKwogICNzY2FsZV95X2xvZzEwKCkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKDIxLDIyKSwgbGFiZWxzID0gc3BlY2llcy5sYWJlbCkgKwogICNzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJ3aGl0ZSIsICJncmF5NDAiKSwgZ3VpZGUgPSAibm9uZSIpICsKICAjZmFjZXRfd3JhcCh+U3BlY2llcywgc2NhbGVzID0gImZyZWVfeCIsIGxhYmVsbGVyID0gYXNfbGFiZWxsZXIoc3BlY2llcy5sYWJlbCkpICsKICBmYWNldF93cmFwKH4gbGVuXzEsIHNjYWxlcyA9ICJmcmVlIikgKwogIHhsYWIoIkxlbmd0aCBvZiBwcmltYXJ5IHN0cmVzcyAobWluKSIpICsgeWxhYigiQVNSIHNjb3JlIChyJy9yKSIpICsKICB0aGVtZV9jb3dwbG90KGxpbmVfc2l6ZSA9IDAuNykKcAojZ2dzYXZlKCIuLi9vdXRwdXQvMjAyMzAxMDMtQVNSLXNjb3JlLWFjcm9zcy1ub1BpLWxlbmd0aC1zZXAtcGFuZWwucG5nIiwgd2lkdGggPSA2LCBoZWlnaHQgPSAzKQpgYGAKCiMjIFMzYTogdEJPT0gKXyoqR29hbCoqXwoKLSBEZXRlcm1pbmUgaWYgcGhvc3BoYXRlIHN0YXJ2YXRpb24gYWxzbyBwcm92aWRlcyBBU1IgZm9yIG90aGVyIG94aWRhbnRzIHRoYW4gSDJPMgoKXyoqRXhwZXJpbWVudCoqXwoKLSBIYW54aSB0ZXN0ZWQgdGVydC1idXR5bCBoeWRyb3Blcm94aWRlICh0Qk9PSCksIG1lbmFkaW9uZSBhbmQgbWVuYWRpb25lIHNvZGl1bSBiaXN1bGZpdGUgKE1TQiksIGZvbGxvd2luZyB0aGUgc2FtZSBwcm9jZWR1cmUgYXMgSmlueWUgZGlkIGZvciBIMk8yCgpfKipEYXRhKipfCgoqKk1haW4gZGF0YXNldCoqOiAKClNwZWNpZXMgICAgICAgT3hpZGFudCAgICAgQ29uY2VudHJhdGlvbiAgICAgICAgICAgI1JlcHMgICBEYXRlcwotLS0tLS0tLS0tLSAgIC0tLS0tLS0tICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tICAgIC0tLS0tICAgLS0tLS0tLS0tLQpDLiBnbGFicmF0YSAgIHRCT09IICAgICAgIDAsIDEsIDEuNSwgMiBtTSAgICAgICAgIDYgICAgICAgOC8yMy04LzMxCkMuIGdsYWJyYXRhICAgTWVuYWRpb25lICAgMCwgMjUwLCAzMDAsIDM1MCB1TSAgICAgNiAgICAgICA3LzE3LTcvMjYKQy4gZ2xhYnJhdGEgICBNU0IgICAgICAgICAwLCAzMDAsIDM1MCwgNDAwIG1NICAgICA2ICAgICAgIDkvMy05LzgKCl8qKkFuYWx5c2lzKipfCgojIyMgUmVhZCBhbmQgZm9ybWF0IGRhdGEKYGBge3J9CnRtcCA8LSByZWFkX3RzdigiLi4vaW5wdXQvMjAyMzA5MDEtdEJPT0gtQVNSLUNGVS1odC50c3YiLAogICAgICAgICAgICAgICAgY29sX3R5cGVzID0gY29scygpLCBjb21tZW50ID0gIiMiKSAlPiUgCiAgbXV0YXRlKAogICAgc2NhbGVkID0gQ291bnQgKiBEaWx1dGlvbnMgKiAxZS0yCiAgKQoKZGF0LnMzYSA8LSB0bXAgJT4lIAogICMgcmVtb3ZlIHRoZSBwaG9zcGhhdGUgc3RhcnZhdGlvbiBleHBlcmltZW50cyAtIHRoZXkgd2VyZSBpbmNsdWRlZCBhcyBwb3NpdGl2ZQogICMgY29udHJvbHMsIGJ1dCBiZWNhdXNlIHRoZXJlIGlzIG9ubHkgb25lIHJlcGxpY2F0ZSBhbmQgdGhlIHNlY29uZGFyeSBzdHJlc3MKICAjIHdhcyBhcHBsaWVkIGZvciAzIGluc3RlYWQgb2YgMiBob3VycywgQ0ZVIGlzIGV4dHJlbWVseSBsb3cgYW5kIG5vdCBjb25jbHVzaXZlCiAgZmlsdGVyKExlbl8yICE9ICIzIGhyIikgJT4lIAogICMgcmVtb3ZlIHVuaW5mb3JtYXRpdmUgLyBub252YXJpYWJsZSBjb2x1bW5zIAogIHNlbGVjdCgtTGVuXzEsIC1MZW5fMiwgLVNwZWNpZXMsIC1TdHJhaW4pICU+JSAKICAjIGdyb3VwIGJ5IGV4cGVyaW1lbnQgYW5kIFt0Qk9PaF0gdG8gY2FsY3VsYXRlIHIgKE1PL01NKSBvciByJyAoUE8vUE0pCiAgc2VwYXJhdGUoR3JvdXAsIGludG8gPSBjKCJQcmltYXJ5IiwgIlNlY29uZGFyeSIpLCBzZXAgPSAxKSAlPiUgCiAgZ3JvdXBfYnkoRGF0ZSwgUHJpbWFyeSkgJT4lIAogICMgY2FsY3VsYXRlICUgc3Vydml2YWwKICBtdXRhdGUoc2NhbGVkX00gPSBzY2FsZWRbU2Vjb25kYXJ5ID09ICJNIl0sCiAgICAgICAgIHIgPSBudW0oc2NhbGVkIC8gc2NhbGVkW1NlY29uZGFyeSA9PSAiTSJdLCBkaWdpdHMgPSAzKSkgJT4lIAogICMgcmVtb3ZlIHRoZSBzZWNvbmRhcnkgbW9jayBhcyB0aGUgaW5mb3JtYXRpb24gYXJlIGFsbCB1c2VkCiAgZmlsdGVyKFNlY29uZGFyeSAhPSAiTSIpICU+JSAKICBtdXRhdGUoCiAgICBQcmltYXJ5ID0gZmFjdG9yKFByaW1hcnksIGxldmVscyA9IGMoIk0iLCAiUCIpLCAKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTW9jayIsICItUGkiKSksCiAgICB0Qk9PSCA9IGZhY3Rvcih0Qk9PSCwgbGV2ZWxzID0gYygiMC41IG1NIiwgIjEgbU0iLCAiMS41IG1NIiwgIjIgbU0iKSkKICApCmRhdC5zM2EKYGBgCgojIyMgUGxvdCAoYWxsIGRhdGEpCmBgYHtyfQpkYXQuczNhICU+JSAKICAjIGxlYXZlIG91dCB0aGUgbG93ZXN0IGNvbmNlbnRyYXRpb24gaW4gZWFjaCBncm91cAogICNmaWx0ZXIoIUgyTzIgJWluJSBjKCIyIG1NIiwgIjYwIG1NIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB0Qk9PSCwgeSA9IHIpKSArICNwLnN1cnZpdmFsWy0zXSArCiAgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBQcmltYXJ5KSwgc3Ryb2tlID0gMSwgc2l6ZSA9IDIsIAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjcpKSArCiAgc3RhdF9zdW1tYXJ5KGFlcyhncm91cCA9IFByaW1hcnkpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuNyksCiAgICAgICAgICAgICAgIGZ1biA9IG1lYW4sIGZ1bi5tYXggPSBtZWFuLCBmdW4ubWluID0gbWVhbiwKICAgICAgICAgICAgICAgZ2VvbSA9ICJjcm9zc2JhciIsIGNvbG9yID0gInJlZCIsIHdpZHRoID0gMC41KSArCiAgZmFjZXRfd3JhcCh+IHRCT09ILCBucm93ID0gMSwgc2NhbGVzID0gImZyZWVfeCIpICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygiTW9jayIgPSAxLCAiLVBpIiA9IDE2KSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsKICB4bGFiKCJ0Qk9PSCIpICsgeWxhYigiJSBzdXJ2aXZhbCIpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNCwgYmFzZV9saW5lX3NpemUgPSAxKSArCiAgcGFuZWxfYm9yZGVyKGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEpICsKICB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMSksIGZhY2UgPSAzKSwKICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCj4gRnJvbSB0aGUgcGxvdCwgaXQgaXMgY2xlYXIgdGhhdCBwaG9zcGhhdGUgc3RhcnZhdGlvbiBkb2VzIE5PVCBwcm92aWRlIEFTUiBmb3IgdEJPT0gKPiBiZWxvdyB3ZSB3aWxsIGZvY3VzIG9uIHRoZSAyIG1NIGRhdGFzZXQsIGFzIHRoZSBiYXNhbCBzdXJ2aXZhbCByYXRlIGlzIH41JQoKIyMjIFN0YXRpc3RpY2FsIHRlc3QgZm9yIEFTUgpgYGB7cn0KdG1wIDwtIGRhdC5zM2EgJT4lIAogIGZpbHRlcih0Qk9PSCA9PSAiMiBtTSIpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gRGF0ZSwgbmFtZXNfZnJvbSA9IFByaW1hcnksIHZhbHVlc19mcm9tID0gcikgJT4lIAogIG11dGF0ZShBU1IgPSBgLVBpYC9gTW9ja2ApCgp0bXAKCnggPC0gSG1pc2M6OnNtZWFuLmNsLmJvb3QodG1wJEFTUikKCnNwcmludGYoIkFTUl9zY29yZSBtZWFuID0gJS4yZiwgOTUlJSBDSSBieSBib290c3RyYXAgPSBbJS4yZiwgJS4yZl0iLCB4WzFdLCB4WzJdLCB4WzNdKQoKd2l0aCh0bXAsIHQudGVzdChhcy5udW1lcmljKGAtUGlgKSwgYXMubnVtZXJpYyhNb2NrKSwgcGFpcmVkID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAiZyIpKQoKd2l0aCh0bXAsIHdpbGNveC50ZXN0KGAtUGlgLCBNb2NrLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpCmBgYAoKIyMgUzNiOiBNZW5hZGlvbmUKXyoqR29hbCoqXwoKLSBEZXRlcm1pbmUgaWYgcGhvc3BoYXRlIHN0YXJ2YXRpb24gYWxzbyBwcm92aWRlcyBBU1IgZm9yIG90aGVyIG94aWRhbnRzIHRoYW4gSDJPMgoKXyoqRXhwZXJpbWVudCoqXwoKLSBIYW54aSB0ZXN0ZWQgdGVydC1idXR5bCBoeWRyb3Blcm94aWRlICh0Qk9PSCksIG1lbmFkaW9uZSBhbmQgbWVuYWRpb25lIHNvZGl1bSBiaXN1bGZpdGUgKE1TQiksIGZvbGxvd2luZyB0aGUgc2FtZSBwcm9jZWR1cmUgYXMgSmlueWUgZGlkIGZvciBIMk8yCgpfKipBbmFseXNpcyoqXwoKIyMjIFJlYWQgYW5kIGZvcm1hdCBkYXRhCmBgYHtyfQp0bXAgPC0gcmVhZF90c3YoIi4uL2lucHV0LzIwMjMwODAxLW1lbmFkaW9uZS1BU1ItQ0ZVLWh0LnRzdiIsCiAgICAgICAgICAgICAgICBjb2xfdHlwZXMgPSBjb2xzKCksIGNvbW1lbnQgPSAiIyIpICU+JSAKICBtdXRhdGUoCiAgICBzY2FsZWQgPSBDb3VudCAqIERpbHV0aW9ucyAqIDFlLTIKICApCgpkYXQuczNiIDwtIHRtcCAlPiUgCiAgIyByZW1vdmUgdW5pbmZvcm1hdGl2ZSAvIG5vbnZhcmlhYmxlIGNvbHVtbnMgCiAgc2VsZWN0KC1MZW5fMSwgLUxlbl8yLCAtU3BlY2llcywgLVN0cmFpbikgJT4lIAogICMgZ3JvdXAgYnkgZXhwZXJpbWVudCBhbmQgW3RCT09oXSB0byBjYWxjdWxhdGUgciAoTU8vTU0pIG9yIHInIChQTy9QTSkKICBzZXBhcmF0ZShHcm91cCwgaW50byA9IGMoIlByaW1hcnkiLCAiU2Vjb25kYXJ5IiksIHNlcCA9IDEpICU+JSAKICBncm91cF9ieShEYXRlLCBQcmltYXJ5KSAlPiUgCiAgIyBjYWxjdWxhdGUgJSBzdXJ2aXZhbAogIG11dGF0ZShzY2FsZWRfTSA9IHNjYWxlZFtTZWNvbmRhcnkgPT0gIk0iXSwKICAgICAgICAgciA9IHNjYWxlZCAvIHNjYWxlZFtTZWNvbmRhcnkgPT0gIk0iXSkgJT4lIAogICMgcmVtb3ZlIHRoZSBzZWNvbmRhcnkgbW9jayBhcyB0aGUgaW5mb3JtYXRpb24gYXJlIGFsbCB1c2VkCiAgZmlsdGVyKFNlY29uZGFyeSAhPSAiTSIpICU+JSAKICBtdXRhdGUoCiAgICBQcmltYXJ5ID0gZmFjdG9yKFByaW1hcnksIGxldmVscyA9IGMoIk0iLCAiUCIpLCAKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTW9jayIsICItUGkiKSksCiAgICBDb25jZW50cmF0aW9uID0gZmFjdG9yKENvbmNlbnRyYXRpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIjI1MCB1TSIsICIzMDAgdU0iLCAiMzUwIHVNIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiNDAwIHVNIiwgIjQ1MCB1TSIpKSwKICAgIEZsYWcgPSBDb3VudCA8IDEwCiAgKSAlPiUgCiAgcmVuYW1lKE1lbmFkaW9uZSA9IENvbmNlbnRyYXRpb24pCmRhdC5zM2IKYGBgCgojIyMgUGxvdCAoYWxsIGRhdGEpCmBgYHtyfQpkYXQuczNiICU+JSAKICAjIGxlYXZlIG91dCB0aGUgbG93ZXN0IGNvbmNlbnRyYXRpb24gaW4gZWFjaCBncm91cAogICNmaWx0ZXIoIUgyTzIgJWluJSBjKCIyIG1NIiwgIjYwIG1NIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBNZW5hZGlvbmUsIHkgPSByKSkgKyAjcC5zdXJ2aXZhbFstM10gKwogIGdlb21fcG9pbnQoYWVzKHNoYXBlID0gUHJpbWFyeSwgY29sb3IgPSBGbGFnKSwgc3Ryb2tlID0gMSwgc2l6ZSA9IDIsIAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjcpKSArCiAgc3RhdF9zdW1tYXJ5KGFlcyhncm91cCA9IFByaW1hcnkpLAogICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuNyksCiAgICAgICAgICAgICAgIGZ1biA9IG1lYW4sIGZ1bi5tYXggPSBtZWFuLCBmdW4ubWluID0gbWVhbiwKICAgICAgICAgICAgICAgZ2VvbSA9ICJjcm9zc2JhciIsIGNvbG9yID0gInJlZCIsIHdpZHRoID0gMC41KSArCiAgZmFjZXRfd3JhcCh+IE1lbmFkaW9uZSwgbnJvdyA9IDEsIHNjYWxlcyA9ICJmcmVlX3giKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoIk1vY2siID0gMSwgIi1QaSIgPSAxNikpICsKICBzY2FsZV9jb2xvcl9tYW51YWwoIkNvdW50IDwgMTAiLCB2YWx1ZXMgPSBjKCJncmF5MTAiLCAiZ3JlZW4zIikpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50KSArCiAgeGxhYigiTWVuYWRpb25lIikgKyB5bGFiKCIlIHN1cnZpdmFsIikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0LCBiYXNlX2xpbmVfc2l6ZSA9IDEpICsKICBwYW5lbF9ib3JkZXIoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMSkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgxKSwgZmFjZSA9IDMpLAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpCmBgYAoKPiB0aGUgd2hvbGUgY29uY2VudHJhdGlvbiBzZXJpZXMgc2hvd3MgY29uc2lzdGVudCB0cmVuZCBvZiBBU1IuIDQwMCB1TSB3b3VsZCBoYXZlCj4gYmVlbiBhIGdvb2QgY29uY2VudHJhdGlvbiB0byBmb2N1cyBvbiwgYnV0IHdlIGRvbid0IGhhdmUgZW5vdWdoIHJlcGxpY2F0ZXMgYXQgCj4gdGhpcyBjb25jZW50cmF0aW9uCgojIyMgU3RhdGlzdGljYWwgdGVzdCBmb3IgQVNSCldlIGZvY3VzIG9uIDM1MCB1TSBzZXQgYmVjYXVzZSBpdCBzaG93cyBBU1IgYW5kIGhhdmUgNSB1c2FibGUgcmVwbGljYXRlcy4KCmBgYHtyfQp0bXAgPC0gZGF0LnMzYiAlPiUgCiAgZmlsdGVyKE1lbmFkaW9uZSA9PSAiMzUwIHVNIiwgIUZsYWcpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gRGF0ZSwgbmFtZXNfZnJvbSA9IFByaW1hcnksIHZhbHVlc19mcm9tID0gcikgJT4lIAogIG11dGF0ZShBU1IgPSBgLVBpYC9gTW9ja2ApICU+JSAKICBuYS5vbWl0KCkKCnRtcAoKeCA8LSBIbWlzYzo6c21lYW4uY2wuYm9vdCh0bXAkQVNSKQoKc3ByaW50ZigiQVNSX3Njb3JlIG1lYW4gPSAlLjJmLCA5NSUlIENJIGJ5IGJvb3RzdHJhcCA9IFslLjJmLCAlLjJmXSIsIHhbMV0sIHhbMl0sIHhbM10pCgp3aXRoKHRtcCwgdC50ZXN0KGFzLm51bWVyaWMoYC1QaWApLCBhcy5udW1lcmljKE1vY2spLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpCgp3aXRoKHRtcCwgd2lsY294LnRlc3QoYC1QaWAsIE1vY2ssIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKYGBgCgojIyBTM2I6IE1lbmFkaW9uZSBzb2RpdW0gYmlzdWxmaXRlCl8qKkdvYWwqKl8KCi0gRGV0ZXJtaW5lIGlmIHBob3NwaGF0ZSBzdGFydmF0aW9uIGFsc28gcHJvdmlkZXMgQVNSIGZvciBvdGhlciBveGlkYW50cyB0aGFuIEgyTzIKCl8qKkV4cGVyaW1lbnQqKl8KCi0gSGFueGkgdGVzdGVkIHRlcnQtYnV0eWwgaHlkcm9wZXJveGlkZSAodEJPT0gpLCBtZW5hZGlvbmUgYW5kIG1lbmFkaW9uZSBzb2RpdW0gYmlzdWxmaXRlIChNU0IpLCBmb2xsb3dpbmcgdGhlIHNhbWUgcHJvY2VkdXJlIGFzIEppbnllIGRpZCBmb3IgSDJPMgoKXyoqQW5hbHlzaXMqKl8KCiMjIyBSZWFkIGFuZCBmb3JtYXQgZGF0YQpOb3RlIHRoYXQgd2Ugd2lsbCBvdmVyd3JpdGUgZGF0LnMzYi4KYGBge3J9CnRtcCA8LSByZWFkX3RzdigiLi4vaW5wdXQvMjAyMzA5MTAtTVNCLUFTUi1DRlUtaHQudHN2IiwKICAgICAgICAgICAgICAgIGNvbF90eXBlcyA9IGNvbHMoKSwgY29tbWVudCA9ICIjIikgJT4lIAogIG11dGF0ZSgKICAgIHNjYWxlZCA9IENvdW50ICogRGlsdXRpb25zICogMWUtMgogICkKCmRhdC5zM2IgPC0gdG1wICU+JSAKICAjIHJlbW92ZSB0aGUgcGhvc3BoYXRlIHN0YXJ2YXRpb24gZXhwZXJpbWVudHMgLSB0aGV5IHdlcmUgaW5jbHVkZWQgYXMgcG9zaXRpdmUKICAjIGNvbnRyb2xzLCBidXQgYmVjYXVzZSB0aGVyZSBpcyBvbmx5IG9uZSByZXBsaWNhdGUgYW5kIHRoZSBzZWNvbmRhcnkgc3RyZXNzCiAgIyB3YXMgYXBwbGllZCBmb3IgMyBpbnN0ZWFkIG9mIDIgaG91cnMsIENGVSBpcyBleHRyZW1lbHkgbG93IGFuZCBub3QgY29uY2x1c2l2ZQogIGZpbHRlcihMZW5fMiAhPSAiMyBociIpICU+JSAKICAjIHJlbW92ZSB1bmluZm9ybWF0aXZlIC8gbm9udmFyaWFibGUgY29sdW1ucyAKICBzZWxlY3QoLUxlbl8xLCAtTGVuXzIsIC1TcGVjaWVzLCAtU3RyYWluKSAlPiUgCiAgIyBncm91cCBieSBleHBlcmltZW50IGFuZCBbdEJPT2hdIHRvIGNhbGN1bGF0ZSByIChNTy9NTSkgb3IgcicgKFBPL1BNKQogIHNlcGFyYXRlKEdyb3VwLCBpbnRvID0gYygiUHJpbWFyeSIsICJTZWNvbmRhcnkiKSwgc2VwID0gMSkgJT4lIAogIGdyb3VwX2J5KERhdGUsIFByaW1hcnkpICU+JSAKICAjIGNhbGN1bGF0ZSAlIHN1cnZpdmFsCiAgbXV0YXRlKHNjYWxlZF9NID0gc2NhbGVkW1NlY29uZGFyeSA9PSAiTSJdLAogICAgICAgICByID0gbnVtKHNjYWxlZCAvIHNjYWxlZFtTZWNvbmRhcnkgPT0gIk0iXSwgZGlnaXRzID0gMykpICU+JSAKICAjIHJlbW92ZSB0aGUgc2Vjb25kYXJ5IG1vY2sgYXMgdGhlIGluZm9ybWF0aW9uIGFyZSBhbGwgdXNlZAogIGZpbHRlcihTZWNvbmRhcnkgIT0gIk0iKSAlPiUgCiAgbXV0YXRlKAogICAgUHJpbWFyeSA9IGZhY3RvcihQcmltYXJ5LCBsZXZlbHMgPSBjKCJNIiwgIlAiKSwgCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk1vY2siLCAiLVBpIikpLAogICAgTWVuYWRpb25lID0gZmFjdG9yKENvbmNlbnRyYXRpb24sIGxldmVscyA9IGMoIjMwMCBtTSIsICIzNTAgbU0iLCAiNDAwIG1NIiwgIjYwbU0gSDJPMiIpKQogICkKZGF0LnMzYgpgYGAKCiMjIyBQbG90IChhbGwgZGF0YSkKYGBge3J9CmRhdC5zM2IgJT4lIAogICMgbGVhdmUgb3V0IHRoZSBsb3dlc3QgY29uY2VudHJhdGlvbiBpbiBlYWNoIGdyb3VwCiAgI2ZpbHRlcighSDJPMiAlaW4lIGMoIjIgbU0iLCAiNjAgbU0iKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IE1lbmFkaW9uZSwgeSA9IHIpKSArICNwLnN1cnZpdmFsWy0zXSArCiAgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBQcmltYXJ5KSwgc3Ryb2tlID0gMSwgc2l6ZSA9IDIsIAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjcpKSArCiAgc3RhdF9zdW1tYXJ5KGFlcyhncm91cCA9IFByaW1hcnkpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuNyksCiAgICAgICAgICAgICAgIGZ1biA9IG1lYW4sIGZ1bi5tYXggPSBtZWFuLCBmdW4ubWluID0gbWVhbiwKICAgICAgICAgICAgICAgZ2VvbSA9ICJjcm9zc2JhciIsIGNvbG9yID0gInJlZCIsIHdpZHRoID0gMC41KSArCiAgZmFjZXRfd3JhcCh+IE1lbmFkaW9uZSwgbnJvdyA9IDEsIHNjYWxlcyA9ICJmcmVlX3giKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoIk1vY2siID0gMSwgIi1QaSIgPSAxNikpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50KSArCiAgeGxhYigiTVNCIikgKyB5bGFiKCIlIHN1cnZpdmFsIikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0LCBiYXNlX2xpbmVfc2l6ZSA9IDEpICsKICBwYW5lbF9ib3JkZXIoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMSkgKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgxKSwgZmFjZSA9IDMpLAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpCmBgYAoKPiBhdCB0aGUgaGlnaGVzdCwgNDAwIG1NIGNvbmNlbnRyYXRpb24sIHRoZXJlIHNlZW1zIHRvIGJlIEFTUgo+IGJlbG93IHdlIHdpbGwgZm9jdXMgb24gdGhlIDQwMCBtTSBkYXRhc2V0LCB3aGVyZSB0aGUgYmFzYWwgc3Vydml2YWwgcmF0ZSBpcyB+MSUKCiMjIyBQbG90IChjb21iaW5lIHdpdGggdEJPT0gpCmBgYHtyfQpkYXQuczNhYiA8LSBiaW5kX3Jvd3MoCiAgdEJPT0ggPSBkYXQuczNhICU+JSBmaWx0ZXIodEJPT0ggPT0gIjIgbU0iKSAlPiUgcmVuYW1lKENvbmNlbnRyYXRpb24gPSB0Qk9PSCksCiAgTVNCID0gZGF0LnMzYiAlPiUgZmlsdGVyKENvbmNlbnRyYXRpb24gPT0gIjQwMCBtTSIpICU+JSBzZWxlY3QoLU1lbmFkaW9uZSksCiAgSDJPMiA9IGRhdC5zM2IgJT4lIGZpbHRlcihDb25jZW50cmF0aW9uID09ICI2MG1NIEgyTzIiKSAlPiUgc2VsZWN0KC1NZW5hZGlvbmUpLAogIC5pZCA9ICJST1MiCikgJT4lIAogbXV0YXRlKENvbmNlbnRyYXRpb24gPSBnc3ViKCI2MG1NIEgyTzIiLCAiNjAgbU0iLCBDb25jZW50cmF0aW9uKSwKICAgICAgICBST1MgPSBmYWN0b3IoUk9TLCBsZXZlbHMgPSBjKCJ0Qk9PSCIsICJNU0IiLCAiSDJPMiIpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJ0Qk9PSCIsICJNU0IiLCAiSFsyXSpPWzJdIikpKSAKZGF0LnMzYWIgJT4lIAogIGdncGxvdChhZXMoeCA9IENvbmNlbnRyYXRpb24sIHkgPSByKSkgKyAjcC5zdXJ2aXZhbFstM10gKwogIGdlb21fcG9pbnQoYWVzKHNoYXBlID0gUHJpbWFyeSksIHN0cm9rZSA9IDEsIHNpemUgPSAyLCAKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC43KSkgKwogIHN0YXRfc3VtbWFyeShhZXMoZ3JvdXAgPSBQcmltYXJ5KSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjcpLAogICAgICAgICAgICAgICBmdW4gPSBtZWFuLCBmdW4ubWF4ID0gbWVhbiwgZnVuLm1pbiA9IG1lYW4sCiAgICAgICAgICAgICAgIGdlb20gPSAiY3Jvc3NiYXIiLCBjb2xvciA9ICJyZWQiLCB3aWR0aCA9IDAuNSkgKwogIGZhY2V0X3dyYXAofiBST1MsIG5yb3cgPSAxLCBzY2FsZXMgPSAiZnJlZV94IiwgbGFiZWxsZXIgPSBsYWJlbF9wYXJzZWQpICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygiTW9jayIgPSAxLCAiLVBpIiA9IDE2KSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsKICB4bGFiKE5VTEwpICsgeWxhYigiJSBzdXJ2aXZhbCIpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNCwgYmFzZV9saW5lX3NpemUgPSAxKSArCiAgYmFja2dyb3VuZF9ncmlkKG1ham9yID0gIm5vbmUiKSArCiAgcGFuZWxfYm9yZGVyKGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEpICsKICB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMSksIGZhY2UgPSAzKSwKICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKQpnZ3NhdmUoIi4uL291dHB1dC8yMDIzMDkxMi1maWdzMy1vdGhlci1yb3MucG5nIiwgd2lkdGggPSA1LCBoZWlnaHQgPSAzKQpgYGAKCiMjIyBTdGF0aXN0aWNhbCB0ZXN0IGZvciBBU1IKV2UgZm9jdXMgb24gNDAwIG1NIHNldCBiZWNhdXNlIGl0IHNob3dzIHRoZSBtb3N0IGNsZWFyIEFTUiBlZmZlY3QuIE5vdGUgdGhhdCBhIHRlc3QgZG9uZSBmb3IgdGhlIDM1MCBtTSwgd2hpY2ggbGVhZHMgdG8gYSBzaW1pbGFyIDUlIGJhc2FsIHN1cnZpdmFsIHJhdGUgYXMgMiBtTSB0Qk9PSCwgc2hvd2VkIGEgbW9kZXJhdGUgQVNSIChtZWFuID0gMS41NSkgZWZmZWN0LCB3aXRoIGEgUC12YWx1ZSBhcHByb2FjaGluZyAwLjA1ICgwLjA4KS4gSmlueWUncyBzcG90dGluZyBhc3NheSBhbHNvIHNob3dlZCBjbGVhciBBU1IgcmVzdWx0IGF0IDM1MCBtTS4KCmBgYHtyfQp0bXAgPC0gZGF0LnMzYiAlPiUgCiAgZmlsdGVyKE1lbmFkaW9uZSA9PSAiNDAwIG1NIikgJT4lIAogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBEYXRlLCBuYW1lc19mcm9tID0gUHJpbWFyeSwgdmFsdWVzX2Zyb20gPSByKSAlPiUgCiAgbXV0YXRlKEFTUiA9IGAtUGlgL2BNb2NrYCkKCnRtcAoKeCA8LSBIbWlzYzo6c21lYW4uY2wuYm9vdCh0bXAkQVNSKQoKc3ByaW50ZigiQVNSX3Njb3JlIG1lYW4gPSAlLjJmLCA5NSUlIENJIGJ5IGJvb3RzdHJhcCA9IFslLjJmLCAlLjJmXSIsIHhbMV0sIHhbMl0sIHhbM10pCgp3aXRoKHRtcCwgdC50ZXN0KGFzLm51bWVyaWMoYC1QaWApLCBhcy5udW1lcmljKE1vY2spLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpCgp3aXRoKHRtcCwgd2lsY294LnRlc3QoYC1QaWAsIE1vY2ssIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKYGBgCkluIHRoZSBzYW1lIGV4cGVyaW1lbnQsIEFTUiBmb3IgSDJPMiB3YXMgY29uZmlybWVkOgoKYGBge3J9CnRtcCA8LSBkYXQuczNiICU+JSAKICBmaWx0ZXIoTWVuYWRpb25lID09ICI2MG1NIEgyTzIiKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IERhdGUsIG5hbWVzX2Zyb20gPSBQcmltYXJ5LCB2YWx1ZXNfZnJvbSA9IHIpICU+JSAKICBtdXRhdGUoQVNSID0gYC1QaWAvYE1vY2tgKQoKdG1wCgp4IDwtIEhtaXNjOjpzbWVhbi5jbC5ib290KHRtcCRBU1IpCgpzcHJpbnRmKCJBU1Jfc2NvcmUgbWVhbiA9ICUuMmYsIDk1JSUgQ0kgYnkgYm9vdHN0cmFwID0gWyUuMmYsICUuMmZdIiwgeFsxXSwgeFsyXSwgeFszXSkKCndpdGgodG1wLCB0LnRlc3QoYXMubnVtZXJpYyhgLVBpYCksIGFzLm51bWVyaWMoTW9jayksIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKCndpdGgodG1wLCB3aWxjb3gudGVzdChgLVBpYCwgTW9jaywgcGFpcmVkID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAiZyIpKQpgYGAKIyMgRmlnMzogY3RhMeKIhgpfKipHb2FsKipfCgotIERldGVybWluZSBpZiBfQ1RBMV8gaXMgcmVxdWlyZWQgZm9yIHRoZSBBU1IKCl8qKkV4cGVyaW1lbnQqKl8KCi0gSmlueWUgZGVsZXRlZCBfQ1RBMV8gYW5kIGNvbXBhcmVkIEFTUiBpbiB0aGlzIHN0cmFpbiB0byB0aGUgd3QgX0MuIGdsYWJyYXRhXwoKXyoqRGF0YSoqXwoKU3BlY2llcyAgICAgICBTdHJhaW4gICAgICAgICAgIEdlbm90eXBlICAgICBIMk8yICAgICAgICAgCi0tLS0tLS0tICAgICAgLS0tLS0tLS0tLS0tLSAgICAtLS0tLS0tLS0tICAgLS0tLS0tLS0tLS0tCkMuIGdsYWJyYXRhICAgeUgwMDEsIHlIMDAyICAgICB3aWxkdHlwZSAgICAgODAsIDEwMCBtTSAKQy4gZ2xhYnJhdGEgICB5SDI3MSwgeUgyNzIgICAgIF9jdGEx4oiGXyAgICAgIDIuMiwgMi41IG1NIAoKU2l4IHJlcGxpY2F0ZXMsIHR3byBlYWNoIGZyb20gMDcvMDgsIDA3LzExLCAwNy8xMiBvZiAyMDIyLgoKYGBge3J9CnVzZS5mMyA8LSBwYXN0ZTAoYygiMDcvMDgiLCAiMDcvMTEiLCAiMDcvMTIiKSwgIi8yMiIpCnRtcCA8LSAgcmF3ICU+JQogIGZpbHRlcihEYXRlICVpbiUgdXNlLmYzKSAlPiUgCiAgbXV0YXRlKAogICAgc2NhbGVkID0gQ291bnQgKiBEaWx1dGlvbnMgKiAxZS0yCiAgKSAlPiUgCiAgIyByZW1vdmUgdW5pbmZvcm1hdGl2ZSBjb2x1bW5zLiBvbmx5IG9uZSBIMk8yIGNvbmMgdXNlZCBmb3IgZWFjaCBzcGVjaWVzCiAgc2VsZWN0KC1MZW5fMSwgLUxlbl8yLCAtRXhwZXJpbWVudGVyKQojIEFzc3VtZSB0aGUgcmVwbGljYXRlcyB3ZXJlIHBhaXJlZCBpbiB0aGUgb3JkZXIgdGhleSBhcHBlYXIgaW4gdGhlIHRhYmxlLAojIGkuZS4sIHRoZSBmaXJzdCByb3cgaW4gdGhlIE1PLCBNTSwgUE8sIFBNIGdyb3VwcyBiZWxvbmcgdG8gdGhlIHNhbWUgYmlvbG9naWNhbCAKIyByZXBsaWNhdGUsIHdlIGNhbiBkZXJpdmUgdGhyZWUgQVNSX3Njb3JlcyBmb3IgZWFjaCBkYXRlIHggc3BlY2llcyB4IExlbl8xCgpkYXQuZjMgPC0gdG1wICU+JSAKICAjIGdyb3VwIGJ5IHByaW1hcnkgdG8gY2FsY3VsYXRlIHIgKE1PL01NKSBvciByJyAoUE8vUE0pCiAgc2VwYXJhdGUoR3JvdXAsIGludG8gPSBjKCJQcmltYXJ5IiwgIlNlY29uZGFyeSIpLCBzZXAgPSAxKSAlPiUgCiAgZ3JvdXBfYnkoRGF0ZSwgU3RyYWluLCBQcmltYXJ5KSAlPiUgCiAgIyBjYWxjdWxhdGUgJSBzdXJ2aXZhbAogIG11dGF0ZShzY2FsZWRfTSA9IHNjYWxlZFtTZWNvbmRhcnkgPT0gIk0iXSwKICAgICAgICAgciA9IG51bShzY2FsZWQgLyBzY2FsZWRbU2Vjb25kYXJ5ID09ICJNIl0sIGRpZ2l0cyA9IDMpKSAlPiUgCiAgIyByZW1vdmUgdGhlIHNlY29uZGFyeSBtb2NrIGFzIHRoZSBpbmZvcm1hdGlvbiBhcmUgYWxsIHVzZWQKICBmaWx0ZXIoU2Vjb25kYXJ5ICE9ICJNIikKZGF0LmYzCmBgYAojIyMgUGxvdCAoYWxsIGRhdGEpCmBgYHtyfQpkYXQuZjMgJT4lIAogIG11dGF0ZSgKICAgIFByaW1hcnkgPSBmYWN0b3IoUHJpbWFyeSwgbGV2ZWxzID0gYygiTSIsICJQIiksIAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJNb2NrIiwgIi1QaSIpKSwKICAgIEdlbm90eXBlID0gZmFjdG9yKEdlbm90eXBlLCBsZXZlbHMgPSBjKCJ3dCIsICJjdGExzpQiKSwKICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIndpbGR0eXBlIiwgImN0YTHOlCIpKSwKICAgIEdyb3VwID0gZmFjdG9yKEgyTzIsIGxldmVscyA9IGMoIjEwMCBtTSIsICIyLjUgbU0iLCAiODAgbU0iLCAiMi4yIG1NIiksCiAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJIaWdoIiwgIkhpZ2giLCAiTWVkaXVtIiwgIk1lZGl1bSIpKQogICkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gSDJPMiwgeSA9IHIpKSArICNwLnN1cnZpdmFsWy0zXSArCiAgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBQcmltYXJ5KSwgc3Ryb2tlID0gMSwgc2l6ZSA9IDIsIAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpKSArCiAgc3RhdF9zdW1tYXJ5KGFlcyhncm91cCA9IFByaW1hcnkpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuOSksCiAgICAgICAgICAgICAgIGZ1biA9IG1lYW4sIGZ1bi5tYXggPSBtZWFuLCBmdW4ubWluID0gbWVhbiwKICAgICAgICAgICAgICAgZ2VvbSA9ICJjcm9zc2JhciIsIGNvbG9yID0gInJlZCIsIHdpZHRoID0gMC41KSArCiAgZmFjZXRfd3JhcCh+IEdyb3VwICsgR2Vub3R5cGUsIG5yb3cgPSAxLCBzY2FsZXMgPSAiZnJlZV94IikgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKCJNb2NrIiA9IDEsICItUGkiID0gMTYpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkgKwogIHhsYWIoYnF1b3RlKEhbMl0qT1syXX4obU0pKSkgKyB5bGFiKCIlIHN1cnZpdmFsIikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0LCBiYXNlX2xpbmVfc2l6ZSA9IDEpICsKICBwYW5lbF9ib3JkZXIoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMSkgKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgxKSwgZmFjZSA9IDMpLAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpCmBgYAoKIyMjIDEwMCB2cyAyLjUgbU0KVG8gYmUgY29uc2lzdGVudCB3aXRoIHBhbmVsIEMsIHdlIHdpbGwgdXNlIHRoZSAxMDAgbU0gdnMgMi41IG1NIHBhaXIgYW5kIGxlYXZlIG91dCB0aGUgODAgbU0gdnMgMi4yIG1NIHBhaXIuCmBgYHtyfQpkYXQuZjNhIDwtIGRhdC5mMyAlPiUgCiAgbXV0YXRlKCBQcmltYXJ5ID0gZmFjdG9yKFByaW1hcnksIGxldmVscyA9IGMoIk0iLCAiUCIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTW9jayIsICItUGkiKSksCiAgICAgICAgICBHZW5vdHlwZSA9IGZhY3RvcihHZW5vdHlwZSwgbGV2ZWxzID0gYygid3QiLCAiY3RhMc6UIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJ3aWxkdHlwZSIsICJjdGExzpQiKSksCiAgICAgICAgICBHcm91cCA9IGZhY3RvcihIMk8yLCBsZXZlbHMgPSBjKCIxMDAgbU0iLCAiMi41IG1NIiwgIjgwIG1NIiwgIjIuMiBtTSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiSGlnaCIsICJIaWdoIiwgIk1lZGl1bSIsICJNZWRpdW0iKSkpICU+JQogIGZpbHRlcihHcm91cCA9PSAiSGlnaCIpICU+JSAKICBzZWxlY3QoLUdyb3VwKSAlPiUgCiAgdW5ncm91cCgpCiN3cml0ZV90c3YoZGF0LmYzYSwgZmlsZSA9ICIuLi9pbnB1dC8yMDIzMDUyMC1maWctM2QtZGF0YS1oYi50c3YiKQpgYGAKCiMjIyMgUGxvdApgYGB7cn0KcCA8LSBkYXQuZjNhICU+JSAKICBtdXRhdGUoR2Vub3R5cGUgPSBmY3RfcmVjb2RlKEdlbm90eXBlLCAiV1QiID0gIndpbGR0eXBlIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBQcmltYXJ5LCB5ID0gcikpICsKICBnZW9tX3BvaW50KGFlcyhzaGFwZSA9IFByaW1hcnkpLCBzdHJva2UgPSAxLCBzaXplID0gMiwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKDAuMSkpICsKICBzY2FsZV9zaGFwZV9tYW51YWwobmFtZSA9ICIiLCB2YWx1ZXMgPSBjKDEsIDE2KSwgZ3VpZGUgPSAibm9uZSIpICsKICAjc2NhbGVfZmlsbF9tYW51YWwobmFtZSA9IGJxdW90ZShIWzJdKk9bMl0pLCB2YWx1ZXMgPSBjKCJ3aGl0ZSIsICJncmF5ODAiKSkgKwogIHAuc3Vydml2YWxbLTFdICsKICBmYWNldF93cmFwKH5HZW5vdHlwZSArIEgyTzIsIG5yb3cgPSAxKSArCiAgcGFuZWxfYm9yZGVyKGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuNSkgKwogIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkKICAgICAgICApCnAKCiNnZ3NhdmUoIi4uL291dHB1dC8yMDIzMDMwMS1maWczZC1hc3ItY3RhMS5wbmciLCB3aWR0aCA9IDMuMywgaGVpZ2h0ID0gMykKYGBgCgpgYGAKcCA8LSBnZ3Bsb3QoZGF0LmYzYSwgYWVzKHggPSBIMk8yLCB5ID0gcikpICsKICBnZW9tX3BvaW50KGFlcyhzaGFwZSA9IFByaW1hcnkpLCBzdHJva2UgPSAwLjksIHNpemUgPSAyLjUsIAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAwLjMsIGRvZGdlLndpZHRoID0gMC45KSkgKwogIHN0YXRfc3VtbWFyeShhZXMoZ3JvdXAgPSBQcmltYXJ5KSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpLAogICAgICAgICAgICAgICBmdW4gPSBtZWFuLCBmdW4ubWF4ID0gbWVhbiwgZnVuLm1pbiA9IG1lYW4sCiAgICAgICAgICAgICAgIGdlb20gPSAiY3Jvc3NiYXIiLCBjb2xvciA9ICJyZWQiLCB3aWR0aCA9IDAuNSkgKwogIGZhY2V0X3dyYXAofiBHZW5vdHlwZSwgbnJvdyA9IDEsIHNjYWxlcyA9ICJmcmVlX3giKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKG5hbWUgPSAiUHJpbWFyeSBzdHJlc3MiLCB2YWx1ZXMgPSBjKCJNb2NrIiA9IDEsICItUGkiID0gMTYpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkgKwogIHhsYWIoYnF1b3RlKEhbMl0qT1syXX4obU0pKSkgKyB5bGFiKCIlIHN1cnZpdmFsIikgKwogIHRoZW1lX2Nvd3Bsb3QobGluZV9zaXplID0gMS4yKSArCiAgcGFuZWxfYm9yZGVyKGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuNSkgKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgxKSksCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAjc3RyaXAucGxhY2VtZW50ID0gImluc2lkZSIsCiAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgICBsZWdlbmQuanVzdGlmaWNhdGlvbiA9ICJjZW50ZXIiLAogICAgICAgIGxlZ2VuZC5tYXJnaW4gPSBtYXJnaW4oYiA9IC0xMCksCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgwLjkpKSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgwLjkpKSkKcAoKZ2dzYXZlKCIuLi9vdXRwdXQvMjAyMzAzMDEtZmlnM2QtYXNyLWN0YTEucG5nIiwgd2lkdGggPSAzLjUsIGhlaWdodCA9IDMuNSkKYGBgCgpfKipTdGF0aXN0aWNhbCB0ZXN0cyoqXwoKIyMjIyBTdGF0aXN0aWNhbCB0ZXN0CjEuIERldGVybWluZSBpZiB0aGUgYmFzYWwgc3Vydml2YWwgcmF0ZXMgYXJlIGRpZmZlcmVudCBiZXR3ZWVuIHd0IGFuZCBjdGEx4oiGIChXaWxjb3hvbiBzaWduZWQtcmFuayB0ZXN0KQoxLiBEZXRlcm1pbmUgaWYgdGhlIHByaW1hcnkgc3RyZXNzIGVuaGFuY2VkIHRoZSBzdXJ2aXZhbCBpbiBfZWFjaF8gZ2Vub3R5cGUgKFdpbGNveG9uIHNpZ25lZC1yYW5rIHRlc3QpCgpfKipCYXNhbCBzdXJ2aXZhbCByYXRlKipfCgpCZXR3ZWVuIHd0IGFuZCBjdGEx4oiGLCB1bnBhaXJlZCwgcmFuay1zdW0gdGVzdC4KYGBge3J9CnRtcCA8LSBkYXQuZjNhICU+JSAKICBmaWx0ZXIoUHJpbWFyeSA9PSAiTW9jayIpICU+JSAKICBzZWxlY3QoRGF0ZSwgR2Vub3R5cGUsIHIpICU+JSAKICBhcnJhbmdlKEdlbm90eXBlKQoKdG1wICU+JSBncm91cF9ieShHZW5vdHlwZSkgJT4lIHN1bW1hcml6ZShtZWFuID0gbWVhbihyKSwgc2QgPSBudW0oc2QociksIGRpZ2l0cyA9IDMpKQoKd2lsY294LnRlc3QociB+IEdlbm90eXBlLCBwYWlyZWQgPSBGQUxTRSwgZGF0YSA9IHRtcCkKYGBgCgo+IGJhc2FsIHN1cnZpdmFsIHJhdGVzIG5vdCBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBiZXR3ZWVuIGdlbm90eXBlcyBhdCB0aGUgY2hvc2VuIFtIMk8yXQoKXyoqU3Vydml2YWwgcmF0ZSB3aXRoIHRoZSBwcmltYXJ5IHN0cmVzcyoqXwoKQmV0d2VlbiB3dCBhbmQgY3RhMeKIhiwgdW5wYWlyZWQsIHJhbmstc3VtIHRlc3QuCmBgYHtyfQp0bXAgPC0gZGF0LmYzYSAlPiUgCiAgZmlsdGVyKFByaW1hcnkgPT0gIi1QaSIpICU+JSAKICBzZWxlY3QoRGF0ZSwgR2Vub3R5cGUsIHIpICU+JSAKICBhcnJhbmdlKEdlbm90eXBlKQoKdG1wICU+JSBncm91cF9ieShHZW5vdHlwZSkgJT4lIHN1bW1hcml6ZShtZWFuID0gbWVhbihyKSwgc2QgPSBudW0oc2QociksIGRpZ2l0cyA9IDMpKQoKd2lsY294LnRlc3QociB+IEdlbm90eXBlLCBwYWlyZWQgPSBGQUxTRSwgZGF0YSA9IHRtcCkKYGBgCj4gc3Vydml2YWwgcmF0ZXMgd2l0aCBwcmltYXJ5IHN0cmVzcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBiZXR3ZWVuIHd0IGFuZCBjdGEx4oiGCgpfUHJpbWFyeSBzdHJlc3MgZW5oYW5jZWQgaW4gd2lsZHR5cGVfCgpDb21wYXJpc29uIGJldHdlZW4gciBhbmQgcicsIHBhaXJlZCwgc2lnbmVkLXJhbmsgdGVzdC4KYGBge3J9CnRtcCA8LSBkYXQuZjNhICU+JSAKICBmaWx0ZXIoR2Vub3R5cGUgPT0gIndpbGR0eXBlIikgJT4lIAogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKERhdGUsIFN0cmFpbiksIG5hbWVzX2Zyb20gPSBQcmltYXJ5LCB2YWx1ZXNfZnJvbSA9IHIpICU+JSAKICBtdXRhdGUoQVNSID0gYC1QaWAvTW9jaykKCnRtcAoKeCA8LSBIbWlzYzo6c21lYW4uY2wuYm9vdCh0bXAkQVNSKQpzcHJpbnRmKCJBU1Jfc2NvcmUgbWVhbiA9ICUuMmYsIDk1JSUgQ0kgYnkgYm9vdHN0cmFwID0gWyUuMmYsICUuMmZdIiwgeFsxXSwgeFsyXSwgeFszXSkKCndpdGgodG1wLCB0LnRlc3QoYXMubnVtZXJpYyhgLVBpYCksIGFzLm51bWVyaWMoTW9jayksIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKd2l0aCh0bXAsIHdpbGNveC50ZXN0KGAtUGlgLCBNb2NrLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpCndpdGgodG1wLCB3aWxjb3gudGVzdChgLVBpYCwgTW9jaywgcGFpcmVkID0gRkFMU0UsIGFsdGVybmF0aXZlID0gImciKSkKYGBgCgpfUHJpbWFyeSBzdHJlc3MgZWZmZWN0IGluIGN0YTHOlF8KClBhaXJlZCwgc2lnbmVkLXJhbmsgdGVzdApgYGB7cn0KdG1wIDwtIGRhdC5mM2EgJT4lIAogIGZpbHRlcihHZW5vdHlwZSA9PSAiY3RhMc6UIikgJT4lIAogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKERhdGUsIFN0cmFpbiksIG5hbWVzX2Zyb20gPSBQcmltYXJ5LCB2YWx1ZXNfZnJvbSA9IHIpICU+JSAKICBtdXRhdGUoQVNSID0gYC1QaWAvTW9jaykKCnRtcAoKeCA8LSBIbWlzYzo6c21lYW4uY2wuYm9vdCh0bXAkQVNSKQpzcHJpbnRmKCJBU1Jfc2NvcmUgbWVhbiA9ICUuMmYsIDk1JSUgQ0kgYnkgYm9vdHN0cmFwID0gWyUuMmYsICUuMmZdIiwgeFsxXSwgeFsyXSwgeFszXSkKCndpdGgodG1wLCB0LnRlc3QoYXMubnVtZXJpYyhgLVBpYCksIGFzLm51bWVyaWMoTW9jayksIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKd2l0aCh0bXAsIHdpbGNveC50ZXN0KGAtUGlgLCBNb2NrLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpCndpdGgodG1wLCB3aWxjb3gudGVzdChgLVBpYCwgTW9jaywgcGFpcmVkID0gRkFMU0UsIGFsdGVybmF0aXZlID0gImciKSkKYGBgCj4gVGhlcmUgaXMgYSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IEFTUiBlZmZlY3QgaW4gY3RhMeKIhiwgYnV0IHRoZSBlZmZlY3QgaXMgdmVyeSBtaWxkCgpfKipDb21wYXJpbmcgdGhlIEFTUiBlZmZlY3QgaW4gY3RhMc6UIHZzIHdpbGQgdHlwZSoqXwoKVW5wYWlyZWQsIHJhbmstc3VtIHRlc3QKYGBge3J9CnRtcCA8LSBkYXQuZjNhICU+JSAKICAjZmlsdGVyKEdlbm90eXBlID09ICJjdGExzpQiKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoRGF0ZSwgU3RyYWluLCBHZW5vdHlwZSksIG5hbWVzX2Zyb20gPSBQcmltYXJ5LCB2YWx1ZXNfZnJvbSA9IHIpICU+JSAKICBtdXRhdGUoQVNSID0gYC1QaWAvTW9jaykgJT4lIAogIGFycmFuZ2UoR2Vub3R5cGUpCgp0bXAgJT4lIGdyb3VwX2J5KEdlbm90eXBlKSAlPiUgCiAgc3VtbWFyaXplKEFTUl9zY29yZSA9IHBhc3RlKHJvdW5kKGFzLm51bWVyaWMoQVNSKSwxKSwgY29sbGFwc2UgPSAiLCAiKSwgCiAgICAgICAgICAgIG1lYW4gPSBtZWFuKEFTUiksIHNkID0gc2QoQVNSKSkKCnQudGVzdChhcy5udW1lcmljKEFTUikgfiBHZW5vdHlwZSwgcGFpcmVkID0gRkFMU0UsIGRhdGEgPSB0bXApCndpbGNveC50ZXN0KGFzLm51bWVyaWMoQVNSKSB+IEdlbm90eXBlLCBwYWlyZWQgPSBGQUxTRSwgZGF0YSA9IHRtcCkKYGBgCj4gVGhlIGRpZmZlcmVuY2UgaW4gQVNSLXNjb3JlIGJldHdlZW4gX2N0YTHiiIZfIGFuZCB3aWxkIHR5cGUgaXMgc2lnbmlmaWNhbnQgKFAgPSAwLjAwMikKCiMjIyA4MCB2cyAyLjIgbU0KQ29ycmVzcG9uZGluZyByZXN1bHRzIGZvciA4MCBtTSB2cyAyLjIgbU0KYGBge3J9CmRhdC5mM2IgPC0gZGF0LmYzICU+JSAKICBtdXRhdGUoIFByaW1hcnkgPSBmYWN0b3IoUHJpbWFyeSwgbGV2ZWxzID0gYygiTSIsICJQIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJNb2NrIiwgIi1QaSIpKSwKICAgICAgICAgIEdlbm90eXBlID0gZmFjdG9yKEdlbm90eXBlLCBsZXZlbHMgPSBjKCJ3dCIsICJjdGExzpQiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIndpbGR0eXBlIiwgImN0YTHOlCIpKSwKICAgICAgICAgIEdyb3VwID0gZmFjdG9yKEgyTzIsIGxldmVscyA9IGMoIjEwMCBtTSIsICIyLjUgbU0iLCAiODAgbU0iLCAiMi4yIG1NIiksCiAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJIaWdoIiwgIkhpZ2giLCAiTWVkaXVtIiwgIk1lZGl1bSIpKSkgJT4lCiAgZmlsdGVyKEdyb3VwID09ICJNZWRpdW0iKSAlPiUgCiAgdW5ncm91cCgpCmBgYAoKIyMjIyBQbG90CmBgYHtyfQpwIDwtIGdncGxvdChkYXQuZjNiLCBhZXMoeCA9IEgyTzIsIHkgPSByKSkgKwogIGdlb21fcG9pbnQoYWVzKHNoYXBlID0gUHJpbWFyeSksIHN0cm9rZSA9IDAuOSwgc2l6ZSA9IDIuNSwgCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IDAuMywgZG9kZ2Uud2lkdGggPSAwLjkpKSArCiAgc3RhdF9zdW1tYXJ5KGFlcyhncm91cCA9IFByaW1hcnkpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuOSksCiAgICAgICAgICAgICAgIGZ1biA9IG1lYW4sIGZ1bi5tYXggPSBtZWFuLCBmdW4ubWluID0gbWVhbiwKICAgICAgICAgICAgICAgZ2VvbSA9ICJjcm9zc2JhciIsIGNvbG9yID0gInJlZCIsIHdpZHRoID0gMC41KSArCiAgZmFjZXRfd3JhcCh+IEdlbm90eXBlLCBucm93ID0gMSwgc2NhbGVzID0gImZyZWVfeCIpICsKICBzY2FsZV9zaGFwZV9tYW51YWwobmFtZSA9ICJQcmltYXJ5IHN0cmVzcyIsIHZhbHVlcyA9IGMoIk1vY2siID0gMSwgIi1QaSIgPSAxNikpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50KSArCiAgeGxhYihicXVvdGUoSFsyXSpPWzJdfihtTSkpKSArIHlsYWIoIiUgc3Vydml2YWwiKSArCiAgdGhlbWVfY293cGxvdChsaW5lX3NpemUgPSAxLjIpICsKICBwYW5lbF9ib3JkZXIoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMSkgKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgxKSksCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAjc3RyaXAucGxhY2VtZW50ID0gImluc2lkZSIsCiAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgICBsZWdlbmQuanVzdGlmaWNhdGlvbiA9ICJjZW50ZXIiLAogICAgICAgIGxlZ2VuZC5tYXJnaW4gPSBtYXJnaW4oYiA9IC0xMCksCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgwLjkpKSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgwLjkpKSkKcAoKI2dnc2F2ZSgiLi4vb3V0cHV0LzIwMjMwMzAxLWYzYi1hc3ItY3RhMS5wbmciLCB3aWR0aCA9IDMuNSwgaGVpZ2h0ID0gMy41KQpgYGAKCl8qKlN0YXRpc3RpY2FsIHRlc3RzKipfCgojIyMjIFN0YXRpc3RpY2FsIHRlc3QKMS4gRGV0ZXJtaW5lIGlmIHRoZSBiYXNhbCBzdXJ2aXZhbCByYXRlcyBhcmUgZGlmZmVyZW50IGJldHdlZW4gd3QgYW5kIF9jdGEx4oiGXyAoV2lsY294b24gc2lnbmVkLXJhbmsgdGVzdCkKMS4gRGV0ZXJtaW5lIGlmIHRoZSBwcmltYXJ5IHN0cmVzcyBlbmhhbmNlZCB0aGUgc3Vydml2YWwgaW4gX2VhY2hfIGdlbm90eXBlIChXaWxjb3hvbiBzaWduZWQtcmFuayB0ZXN0KQoKX0Jhc2FsIHN1cnZpdmFsIHJhdGVfCkJldHdlZW4gZ2Vub3R5cGVzLCB1bnBhaXJlZCwgcmFuay1zdW0gdGVzdC4KYGBge3J9CnRtcCA8LSBkYXQuZjNiICU+JSAKICBmaWx0ZXIoUHJpbWFyeSA9PSAiTW9jayIpICU+JSAKICBzZWxlY3QoRGF0ZSwgR2Vub3R5cGUsIHIpICU+JSAKICBhcnJhbmdlKEdlbm90eXBlKQp0bXAgJT4lIGdyb3VwX2J5KEdlbm90eXBlKSAlPiUgc3VtbWFyaXplKG1lYW4gPSBtZWFuKHIpLCBzZCA9IG51bShzZChyKSwgZGlnaXRzID0gMykpCndpbGNveC50ZXN0KHIgfiBHZW5vdHlwZSwgcGFpcmVkID0gRkFMU0UsIGRhdGEgPSB0bXApCmBgYAo+IHRoZSBiYXNhbCBzdXJ2aXZhbCByYXRlIGlzIHNsaWdodGx5IGhpZ2hlciBpbiBfY3RhMeKIhl8uIHRoZSBkaWZmZXJlbmNlIGlzIG5vdCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGF0IGEgY29udmVudGlvbmFsIDAuMDUgbGV2ZWwuCgpfUHJpbWFyeSBzdHJlc3MgZW5oYW5jZWQgaW4gd2lsZHR5cGVfCgpDb21wYXJpc29uIGJldHdlZW4gciBhbmQgcicsIHBhaXJlZCwgc2lnbmVkLXJhbmsgdGVzdC4KYGBge3J9CnRtcCA8LSBkYXQuZjNiICU+JSAKICBmaWx0ZXIoR2Vub3R5cGUgPT0gIndpbGR0eXBlIikgJT4lIAogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKERhdGUsIFN0cmFpbiksIG5hbWVzX2Zyb20gPSBQcmltYXJ5LCB2YWx1ZXNfZnJvbSA9IHIpICU+JSAKICBtdXRhdGUoQVNSID0gYC1QaWAvTW9jaykKCnRtcAoKeCA8LSBIbWlzYzo6c21lYW4uY2wuYm9vdCh0bXAkQVNSKQpzcHJpbnRmKCJBU1Jfc2NvcmUgbWVhbiA9ICUuMmYsIDk1JSUgQ0kgYnkgYm9vdHN0cmFwID0gWyUuMmYsICUuMmZdIiwgeFsxXSwgeFsyXSwgeFszXSkKCndpdGgodG1wLCB0LnRlc3QoYXMubnVtZXJpYyhgLVBpYCksIGFzLm51bWVyaWMoTW9jayksIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKd2l0aCh0bXAsIHdpbGNveC50ZXN0KGAtUGlgLCBNb2NrLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpCmBgYAoKX1ByaW1hcnkgc3RyZXNzIGVmZmVjdCBpbiBjdGExzpRfCgpQYWlyZWQsIHNpZ25lZC1yYW5rIHRlc3QKYGBge3J9CnRtcCA8LSBkYXQuZjNiICU+JSAKICBmaWx0ZXIoR2Vub3R5cGUgPT0gImN0YTHOlCIpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhEYXRlLCBTdHJhaW4pLCBuYW1lc19mcm9tID0gUHJpbWFyeSwgdmFsdWVzX2Zyb20gPSByKSAlPiUgCiAgbXV0YXRlKEFTUiA9IGAtUGlgL01vY2spCgp0bXAKCnggPC0gSG1pc2M6OnNtZWFuLmNsLmJvb3QodG1wJEFTUikKc3ByaW50ZigiQVNSX3Njb3JlIG1lYW4gPSAlLjJmLCA5NSUlIENJIGJ5IGJvb3RzdHJhcCA9IFslLjJmLCAlLjJmXSIsIHhbMV0sIHhbMl0sIHhbM10pCgp3aXRoKHRtcCwgdC50ZXN0KGFzLm51bWVyaWMoYC1QaWApLCBhcy5udW1lcmljKE1vY2spLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpCndpdGgodG1wLCB3aWxjb3gudGVzdChgLVBpYCwgTW9jaywgcGFpcmVkID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAiZyIpKQpgYGAKPiBubyBzaWduaWZpY2FudCBlZmZlY3Qgb2YgQVNSIGluIF9jdGEx4oiGXyBhdCB0aGlzIFtIMk8yXSBjb25jZW50cmF0aW9uLgoKXyoqQ29tcGFyaW5nIHRoZSBBU1IgZWZmZWN0IGluIGN0YTHOlCB2cyB3aWxkIHR5cGUqKl8KClVucGFpcmVkLCByYW5rLXN1bSB0ZXN0CmBgYHtyfQp0bXAgPC0gZGF0LmYzYiAlPiUgCiAgI2ZpbHRlcihHZW5vdHlwZSA9PSAiY3RhMc6UIikgJT4lIAogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKERhdGUsIFN0cmFpbiwgR2Vub3R5cGUpLCBuYW1lc19mcm9tID0gUHJpbWFyeSwgdmFsdWVzX2Zyb20gPSByKSAlPiUgCiAgbXV0YXRlKEFTUiA9IGAtUGlgL01vY2spICU+JSAKICBhcnJhbmdlKEdlbm90eXBlKQoKdG1wICU+JSBncm91cF9ieShHZW5vdHlwZSkgJT4lIAogIHN1bW1hcml6ZShBU1Jfc2NvcmUgPSBwYXN0ZShyb3VuZChhcy5udW1lcmljKEFTUiksMSksIGNvbGxhcHNlID0gIiwgIiksIAogICAgICAgICAgICBtZWFuID0gbWVhbihBU1IpLCBzZCA9IHNkKEFTUikpCgp0LnRlc3QoYXMubnVtZXJpYyhBU1IpIH4gR2Vub3R5cGUsIHBhaXJlZCA9IEZBTFNFLCBkYXRhID0gdG1wKQp3aWxjb3gudGVzdChhcy5udW1lcmljKEFTUikgfiBHZW5vdHlwZSwgcGFpcmVkID0gRkFMU0UsIGRhdGEgPSB0bXApCmBgYAoKPiBUaGUgZGlmZmVyZW5jZSBpbiBBU1Itc2NvcmUgYmV0d2VlbiB0aGUgX2N0YTHiiIZfIGFuZCB3aWxkIHR5cGUgaXMgc2lnbmlmaWNhbnQgKFAgPSAwLjAwMikKCiMjIEZpZzMtUzE6IF9DVEExXyBjb21wbGVtZW50YXRpb24KXyoqR29hbCoqXwoKLSBWYWxpZGF0ZSB0aGF0IF9jdGEx4oiGXyByZXN1bHQgaXMgZHVlIHRvIHRoZSBpbnRlbmRlZCBkZWxldGlvbgoKXyoqRXhwZXJpbWVudCoqXwoKLSBKaW55ZSBjb25zdHJ1Y3RlZCBhIF9DVEExXyBjb21wbGVtZW50YXRpb24gc3RyYWluIGJ5IHB1dHRpbmcgdGhlIGdlbmUncyBDRFMgYmFjayB0byBpdHMgZW5kb2dlbm91cyBsb2N1cy4gCi0gSGFueGkgcGVyZm9ybWVkIEFTUiB0byBjb21wYXJlIHRoZSBBU1IgZWZmZWN0IHNpemUgb2YgdGhlIGNvbXBsZW1lbnRhdGlvbiwgdGhlIGRlbGV0aW9uIGFuZCB0aGUgd2lsZCB0eXBlLgoKXyoqRGF0YSoqXwoKU3BlY2llcyAgICAgICBTdHJhaW4gICAgICAgICAgR2Vub3R5cGUgICAgICBIMk8yICAgICAgICAgCi0tLS0tLS0tICAgICAgLS0tLS0tLS0tLS0tLSAgIC0tLS0tLS0tLS0tICAgLS0tLS0tLS0tLS0tLS0KQy4gZ2xhYnJhdGEgICB5SDE4MSAgICAgICAgICAgICB3aWxkdHlwZSAgICA2MCwgODAsIDEwMCBtTSAKQy4gZ2xhYnJhdGEgICB5SDI3MSAgICAgICAgICAgICAgX2N0YTHiiIZfICAgIDIuLCAyLjUsIDMuIG1NIApDLiBnbGFicmF0YSAgIHlIMjg1ICAgICAgICAgICBjdGExOjpDVEExLiAgIDYwLCA4MCwgMTAwIG1NCgpTaXggcmVwbGljYXRlcywgYmV0d2VlbiA3LzMxLzIzIC0gOC80LzIzCgpfKipBbmFseXNpcyoqXwoKIyMjIFJlYWQgYW5kIGZvcm1hdCBkYXRhCmBgYHtyfQp0bXAgPC0gcmVhZF90c3YoIi4uL2lucHV0LzIwMjMwODA2LWZpZy0zc3VwLWN0YTEtY29tcC1kYXRhLWh0LnRzdiIsCiAgICAgICAgICAgICAgICBjb2xfdHlwZXMgPSBjb2xzKCksIGNvbW1lbnQgPSAiIyIpICU+JSAKICBtdXRhdGUoCiAgICBzY2FsZWQgPSBDb3VudCAqIERpbHV0aW9ucyAqIDFlLTIKICApCgpkYXQuZjNzIDwtIHRtcCAlPiUgCiAgIyByZW1vdmUgdW5pbmZvcm1hdGl2ZSBjb2x1bW5zLiBvbmx5IG9uZSBIMk8yIGNvbmMgdXNlZCBmb3IgZWFjaCBzcGVjaWVzCiAgc2VsZWN0KC1MZW5fMSwgLUxlbl8yLCAtU3BlY2llcykgJT4lIAogICMgZ3JvdXAgYnkgZXhwZXJpbWVudCBhbmQgSDJPMiB0byBjYWxjdWxhdGUgciAoTU8vTU0pIG9yIHInIChQTy9QTSkKICBzZXBhcmF0ZShHcm91cCwgaW50byA9IGMoIlByaW1hcnkiLCAiU2Vjb25kYXJ5IiksIHNlcCA9IDEpICU+JSAKICBncm91cF9ieShJbmRleCwgU3RyYWluLCBQcmltYXJ5KSAlPiUgCiAgIyBjYWxjdWxhdGUgJSBzdXJ2aXZhbAogIG11dGF0ZShzY2FsZWRfTSA9IHNjYWxlZFtTZWNvbmRhcnkgPT0gIk0iXSwKICAgICAgICAgciA9IG51bShzY2FsZWQgLyBzY2FsZWRbU2Vjb25kYXJ5ID09ICJNIl0sIGRpZ2l0cyA9IDMpKSAlPiUgCiAgIyByZW1vdmUgdGhlIHNlY29uZGFyeSBtb2NrIGFzIHRoZSBpbmZvcm1hdGlvbiBhcmUgYWxsIHVzZWQKICBmaWx0ZXIoU2Vjb25kYXJ5ICE9ICJNIikKZGF0LmYzcwpgYGAKIyMjIFBsb3QgKGV4Y2x1ZGUgNjAgbU0vMiBtTSkKYGBge3J9CmRhdC5mM3MgJT4lIAogICMgbGVhdmUgb3V0IHRoZSBsb3dlc3QgY29uY2VudHJhdGlvbiBpbiBlYWNoIGdyb3VwCiAgZmlsdGVyKCFIMk8yICVpbiUgYygiMiBtTSIsICI2MCBtTSIpKSAlPiUgCiAgbXV0YXRlKAogICAgUHJpbWFyeSA9IGZhY3RvcihQcmltYXJ5LCBsZXZlbHMgPSBjKCJNIiwgIlAiKSwgCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk1vY2siLCAiLVBpIikpLAogICAgR2Vub3R5cGUgPSBmYWN0b3IoR2Vub3R5cGUsIGxldmVscyA9IGMoInd0IiwgIkNnY3RhMTo6Q2dDVEExIiwgImN0YTE6OlVSQTMiKSwKICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIndpbGR0eXBlIiwgImN0YTE6OkNUQTEiLCAiY3RhMc6UIikpCiAgKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBIMk8yLCB5ID0gcikpICsgI3Auc3Vydml2YWxbLTNdICsKICBnZW9tX3BvaW50KGFlcyhzaGFwZSA9IFByaW1hcnkpLCBzdHJva2UgPSAxLCBzaXplID0gMiwgCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuNykpICsKICBzdGF0X3N1bW1hcnkoYWVzKGdyb3VwID0gUHJpbWFyeSksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC43KSwKICAgICAgICAgICAgICAgZnVuID0gbWVhbiwgZnVuLm1heCA9IG1lYW4sIGZ1bi5taW4gPSBtZWFuLAogICAgICAgICAgICAgICBnZW9tID0gImNyb3NzYmFyIiwgY29sb3IgPSAicmVkIiwgd2lkdGggPSAwLjUpICsKICBmYWNldF93cmFwKH4gR2Vub3R5cGUsIG5yb3cgPSAxLCBzY2FsZXMgPSAiZnJlZV94IikgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKCJNb2NrIiA9IDEsICItUGkiID0gMTYpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkgKwogIHhsYWIoIlByaW1hcnkgc3RyZXNzICg0NSBtaW4pIikgKyB5bGFiKCIlIHN1cnZpdmFsIikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE0LCBiYXNlX2xpbmVfc2l6ZSA9IDEpICsKICBwYW5lbF9ib3JkZXIoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMSkgKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgxKSwgZmFjZSA9IDMpLAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gYygwLjksIDAuOCksCiAgICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpCmBgYAoKIyMjIDgwIHYgMTAwIHYgMyBtTQpCeSB0cmlhbCBhbmQgZXJyb3IsIEkgZm91bmQgODAgbU0gZm9yIHRoZSB3aWxkdHlwZSwgMTAwIG1NIGZvciB0aGUgY29tcGxlbWVudCBzdHJhaW4gYW5kIDMgbU0gZm9yIHRoZSBkZWxldGlvbiBoYWQgcmVsYXRpdmVseSBzaW1pbGFyIGJhc2FsIHN1cnZpdmFsIHJhdGVzLgpgYGB7cn0KZGF0LmYzczEgPC0gZGF0LmYzcyAlPiUgCiAgbXV0YXRlKEdyb3VwID0gcGFzdGUoR2Vub3R5cGUsIEgyTzIsIHNlcCA9ICJfIikpICU+JSAKICAjZmlsdGVyKEgyTzIgJWluJSBjKCIxMDAgbU0iLCAiMyBtTSIpKSAlPiUgCiAgZmlsdGVyKEdyb3VwICVpbiUgYygid3RfODAgbU0iLCAiQ2djdGExOjpDZ0NUQTFfMTAwIG1NIiwgImN0YTE6OlVSQTNfMyBtTSIpKSAlPiUgCiAgc2VsZWN0KC1Hcm91cCkgJT4lIAogIG11dGF0ZSgKICAgIFByaW1hcnkgPSBmYWN0b3IoUHJpbWFyeSwgbGV2ZWxzID0gYygiTSIsICJQIiksIAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJNb2NrIiwgIi1QaSIpKSwKICAgIEdlbm90eXBlID0gZmFjdG9yKEdlbm90eXBlLCBsZXZlbHMgPSBjKCJ3dCIsICJDZ2N0YTE6OkNnQ1RBMSIsICJjdGExOjpVUkEzIiksCiAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJ3aWxkdHlwZSIsICJjdGExOjpDVEExIiwgImN0YTHOlCIpKSkKI3dyaXRlX3RzdihkYXQuZjNhLCBmaWxlID0gIi4uL2lucHV0LzIwMjMwNTIwLWZpZy0zZC1kYXRhLWhiLnRzdiIpCmBgYAoKIyMjIyBQbG90CmBgYHtyfQpwIDwtIGRhdC5mM3MxICU+JSAKICBtdXRhdGUoR2Vub3R5cGUgPSBmY3RfcmVjb2RlKEdlbm90eXBlLCAiV1QiID0gIndpbGR0eXBlIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBQcmltYXJ5LCB5ID0gcikpICsKICBnZW9tX3BvaW50KGFlcyhzaGFwZSA9IFByaW1hcnkpLCBzdHJva2UgPSAxLCBzaXplID0gMiwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKDAuMSkpICsKICBzY2FsZV9zaGFwZV9tYW51YWwobmFtZSA9ICIiLCB2YWx1ZXMgPSBjKDEsIDE2KSwgZ3VpZGUgPSAibm9uZSIpICsKICAjc2NhbGVfZmlsbF9tYW51YWwobmFtZSA9IGJxdW90ZShIWzJdKk9bMl0pLCB2YWx1ZXMgPSBjKCJ3aGl0ZSIsICJncmF5ODAiKSkgKwogIHAuc3Vydml2YWxbLTFdICsKICBmYWNldF93cmFwKH5HZW5vdHlwZSArIEgyTzIsIG5yb3cgPSAxKSArCiAgcGFuZWxfYm9yZGVyKGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuNSkgKwogIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkKICAgICAgICApCnAKCiNnZ3NhdmUoIi4uL291dHB1dC8yMDIzMDgwNi1maWczc3VwLWFzci1jdGExLWNvbXAtMS5wbmciLCB3aWR0aCA9IDUsIGhlaWdodCA9IDMpCmBgYAoKYGBge3J9CiNwIDwtIApkYXQuZjNzMSAlPiUgCiAgbXV0YXRlKCAKICAgIEdlbm90eXBlID0gZmN0X3JlY29kZShHZW5vdHlwZSwgIldUIiA9ICJ3aWxkdHlwZSIpLAogICAgR3JvdXAgPSBwYXN0ZShHZW5vdHlwZSwgSDJPMiwgc2VwID0gIlxuIiksCiAgICByID0gYXMubnVtZXJpYyhyKSkgJT4lIAogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKEluZGV4LCBHcm91cCksIG5hbWVzX2Zyb20gPSBQcmltYXJ5LCB2YWx1ZXNfZnJvbSA9IHIpICU+JSAKICBtdXRhdGUoQVNSID0gYC1QaWAgLyBNb2NrLCBHcm91cCA9IGZjdF9yZWxldmVsKEdyb3VwLCAiV1RcbjgwIG1NIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBHcm91cCwgeSA9IEFTUikpICsKICBnZW9tX3BvaW50KHN0cm9rZSA9IDEsIHNpemUgPSAyLAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIoMC4xKSkgKwogIHN0YXRfc3VtbWFyeShmdW4gPSBtZWFuLCBmdW4ubWF4ID0gbWVhbiwgZnVuLm1pbiA9IG1lYW4sCiAgICAgICAgICAgICAgIGdlb20gPSAiY3Jvc3NiYXIiLCBjb2xvciA9ICJyZWQiLCB3aWR0aCA9IDAuNSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsKICB5bGFiKCIlIHN1cnZpdmFsIikgKwogIHRoZW1lX2Nvd3Bsb3QobGluZV9zaXplID0gMC43LCBmb250X3NpemUgPSAxNCkgKwogIHBhbmVsX2JvcmRlcihjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpICsKICB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAyLCBzaXplID0gcmVsKDEuMikpLAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkKICAgICAgICApCmBgYAoKIyMjIyBTdGF0aXN0aWNhbCB0ZXN0CjEuIERldGVybWluZSBpZiB0aGUgYmFzYWwgc3Vydml2YWwgcmF0ZXMgYXJlIGRpZmZlcmVudCBiZXR3ZWVuIGdlbm90eXBlcyAoV2lsY294b24gc2lnbmVkLXJhbmsgdGVzdCkKMS4gRGV0ZXJtaW5lIGlmIHRoZSBwcmltYXJ5IHN0cmVzcyBlbmhhbmNlZCB0aGUgc3Vydml2YWwgaW4gX2VhY2hfIGdlbm90eXBlIChXaWxjb3hvbiBzaWduZWQtcmFuayB0ZXN0KQoKXyoqQmFzYWwgc3Vydml2YWwgcmF0ZSoqXwoKQmVjYXVzZSB3ZSBoYXZlIHRocmVlIGdyb3VwcyBoZXJlLCBteSBzdHJhdGVneSBpcyB0byBmaXJzdCBwZXJmb3JtIGFuIEFOT1ZBLWxpa2UsIGJ1dCByYW5rLWJhc2VkLCBLcnVzYWwtV2FsbGlzIHRlc3QsIHdoZXJlIHRoZSBudWxsIGh5cG90aGVzaXMgaXMgdGhhdCBhbGwgdGhyZWUgZ3JvdXBzJyBkaXN0cmlidXRpb24gaGFzIHRoZSBzYW1lICJsb2NhdGlvbiIgKD1tZWFuKS4gSSBhbHNvIHBlcmZvcm1lZCBhIHBhaXJ3aXNlIFdpbGNveHNvbiByYW5rIHN1bSB0ZXN0LCBhbHRob3VnaCB0aGF0IGlzIG5vdCBuZWNlc3NhcnkgaWYgdGhlIGZpcnN0IHRlc3QgaXMgZGVlbWVkIGluc2lnbmlmaWNhbnQuCmBgYHtyfQp0bXAgPC0gZGF0LmYzczEgJT4lIAogIGZpbHRlcihQcmltYXJ5ID09ICJNb2NrIikgJT4lIAogIHNlbGVjdChJbmRleCwgR2Vub3R5cGUsIHIpICU+JSAKICBtdXRhdGUociA9IGFzLmRvdWJsZShyKSkgJT4lIAogIGFycmFuZ2UoR2Vub3R5cGUpCgp0bXAgJT4lIGdyb3VwX2J5KEdlbm90eXBlKSAlPiUgc3VtbWFyaXplKG1lYW4gPSBtZWFuKHIpLCBzZCA9IG51bShzZChyKSwgZGlnaXRzID0gMykpCgprcnVza2FsLnRlc3QociB+IEdlbm90eXBlLCBkYXRhID0gdG1wKQpwYWlyd2lzZS53aWxjb3gudGVzdCh4ID0gdG1wJHIsIGcgPSB0bXAkR2Vub3R5cGUpCmBgYAoKPiBiYXNhbCBzdXJ2aXZhbCByYXRlcyBub3Qgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgYmV0d2VlbiBnZW5vdHlwZXMgYXQgdGhlIGNob3NlbiBbSDJPMl0sIGFzIHNob3duIGJ5IGJvdGggdGhlIChBTk9WQS1lcXVpdmFsZW50LCByYW5rLWJhc2VkKSBLcnVza2FsLVdhbGxpcyB0ZXN0IGFuZCB0aGUgKHQtdGVzdCBlcXVpdmFsZW50KSBwYWlyd2lzZSBXaWxjb3hzb24gcmFuay1zdW0gdGVzdCAodW5wYWlyZWQpLiBQLXZhbHVlcyBmcm9tIHRoZSBsYXR0ZXIgd2VyZSBhZGp1c3RlZCBmb3IgbXVsdGlwbGUgY29tcGFyaXNvbiB1c2luZyBIb2xtJ3MgbWV0aG9kICh1bmlmb3JtbHkgbW9yZSBwb3dlcmZ1bCB0aGFuIEJvbmZlcnJvbmkpCgpfKipTdXJ2aXZhbCByYXRlIHdpdGggdGhlIHByaW1hcnkgc3RyZXNzKipfCgpTYW1lIHN0cmF0ZWd5IGFzIGFib3ZlCmBgYHtyfQp0bXAgPC0gZGF0LmYzczEgJT4lIAogIGZpbHRlcihQcmltYXJ5ID09ICItUGkiKSAlPiUgCiAgc2VsZWN0KEluZGV4LCBHZW5vdHlwZSwgcikgJT4lIAogIGFycmFuZ2UoR2Vub3R5cGUpCgp0bXAgJT4lIGdyb3VwX2J5KEdlbm90eXBlKSAlPiUgc3VtbWFyaXplKG1lYW4gPSBtZWFuKHIpLCBzZCA9IG51bShzZChyKSwgZGlnaXRzID0gMykpCgprcnVza2FsLnRlc3QoYXMuZG91YmxlKHIpIH4gR2Vub3R5cGUsIGRhdGEgPSB0bXApCnBhaXJ3aXNlLndpbGNveC50ZXN0KHggPSB0bXAkciwgZyA9IHRtcCRHZW5vdHlwZSwgcGFpcmVkID0gRkFMU0UpCmBgYAo+IHN1cnZpdmFsIHJhdGVzIHdpdGggcHJpbWFyeSBzdHJlc3Mgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgYmV0d2VlbiBjdGEx4oiGIHZzIGVpdGhlciB0aGUgd2lsZHR5cGUgb3IgdGhlIGNvbXBsZW1lbnQsIHdoaWxlIG5vIGRpZmZlcmVuY2Ugd2FzIGRldGVjdGVkIGJldHdlZW4gdGhlIGxhdHRlciB0d28uCgpfKipQcmltYXJ5IHN0cmVzcyBlbmhhbmNlZCBpbiB3aWxkdHlwZSoqXwoKSGVyZSwgSSBmaXJzdCBjYWxjdWxhdGUgdGhlIEFTUiBzY29yZSBhbmQgaXRzIHN1bW1hcnkgc3RhdGlzdGljcy4gVG8gZGV0ZXJtaW5lIGlmIHRoZSBlZmZlY3QgaXMgc2lnbmlmaWNhbnQsIEkgcGVyZm9ybSB0aHJlZSB0eXBlcyBvZiB0ZXN0czoKLSBULXRlc3QsIG1vc3QgcG93ZXJmdWwgYnV0IHJlcXVpcmluZyB0aGUgZGF0YSB0byBiZSBub3JtYWxseSBkaXN0cmlidXRlZCwgd2hpY2ggb3VycyBkb2Vzbid0LgotIFdpbGNveHNvbiBzaWduZWQtcmFuayB0ZXN0LCBwYWlyZWQKLSBXaWxjb3hzb24gcmFuay1zdW0gdGVzdCAoPU1hbm4tV2hpdG5leSdzIFUgdGVzdCksIHVucGFpcmVkCgpJbiB0aGUgcGFwZXIsIHdlIHJlcG9ydCB0aGUgUC12YWx1ZXMgb2YgdGhlIFdpbGNveHNvbiBzaWduZWQtcmFuayB0ZXN0CgpDb21wYXJpc29uIGJldHdlZW4gciBhbmQgcicsIHBhaXJlZCwgc2lnbmVkLXJhbmsgdGVzdC4KYGBge3J9CnRtcCA8LSBkYXQuZjNzMSAlPiUgCiAgZmlsdGVyKEdlbm90eXBlID09ICJ3aWxkdHlwZSIpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhJbmRleCwgU3RyYWluKSwgbmFtZXNfZnJvbSA9IFByaW1hcnksIHZhbHVlc19mcm9tID0gcikgJT4lIAogIG11dGF0ZShBU1IgPSBgLVBpYC9Nb2NrKQoKdG1wCgp4IDwtIEhtaXNjOjpzbWVhbi5jbC5ib290KHRtcCRBU1IpCnNwcmludGYoIkFTUl9zY29yZSBtZWFuID0gJS4yZiwgOTUlJSBDSSBieSBib290c3RyYXAgPSBbJS4yZiwgJS4yZl0iLCB4WzFdLCB4WzJdLCB4WzNdKQoKd2l0aCh0bXAsIHQudGVzdChhcy5udW1lcmljKGAtUGlgKSwgYXMubnVtZXJpYyhNb2NrKSwgcGFpcmVkID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAiZyIpKQp3aXRoKHRtcCwgd2lsY294LnRlc3QoYC1QaWAsIE1vY2ssIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKYGBgCgpfUHJpbWFyeSBzdHJlc3MgZW5oYW5jZWQgaW4gQ1RBMSBjb21wbGVtZW50XwoKQ29tcGFyaXNvbiBiZXR3ZWVuIHIgYW5kIHInLCBwYWlyZWQsIHNpZ25lZC1yYW5rIHRlc3QuCmBgYHtyfQp0bXAgPC0gZGF0LmYzczEgJT4lIAogIGZpbHRlcihHZW5vdHlwZSA9PSAiY3RhMTo6Q1RBMSIpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhJbmRleCwgU3RyYWluKSwgbmFtZXNfZnJvbSA9IFByaW1hcnksIHZhbHVlc19mcm9tID0gcikgJT4lIAogIG11dGF0ZShBU1IgPSBgLVBpYC9Nb2NrKQoKdG1wCgp4IDwtIEhtaXNjOjpzbWVhbi5jbC5ib290KHRtcCRBU1IpCnNwcmludGYoIkFTUl9zY29yZSBtZWFuID0gJS4yZiwgOTUlJSBDSSBieSBib290c3RyYXAgPSBbJS4yZiwgJS4yZl0iLCB4WzFdLCB4WzJdLCB4WzNdKQoKd2l0aCh0bXAsIHQudGVzdChhcy5udW1lcmljKGAtUGlgKSwgYXMubnVtZXJpYyhNb2NrKSwgcGFpcmVkID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAiZyIpKQp3aXRoKHRtcCwgd2lsY294LnRlc3QoYC1QaWAsIE1vY2ssIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKYGBgCgpfKipQcmltYXJ5IHN0cmVzcyBlZmZlY3QgaW4gY3RhMc6UKipfCgpQYWlyZWQsIHNpZ25lZC1yYW5rIHRlc3QKYGBge3J9CnRtcCA8LSBkYXQuZjNzMSAlPiUgCiAgZmlsdGVyKEdlbm90eXBlID09ICJjdGExzpQiKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoSW5kZXgsIFN0cmFpbiksIG5hbWVzX2Zyb20gPSBQcmltYXJ5LCB2YWx1ZXNfZnJvbSA9IHIpICU+JSAKICBtdXRhdGUoQVNSID0gYC1QaWAvTW9jaykKCnRtcAoKeCA8LSBIbWlzYzo6c21lYW4uY2wuYm9vdCh0bXAkQVNSKQpzcHJpbnRmKCJBU1Jfc2NvcmUgbWVhbiA9ICUuMmYsIDk1JSUgQ0kgYnkgYm9vdHN0cmFwID0gWyUuMmYsICUuMmZdIiwgeFsxXSwgeFsyXSwgeFszXSkKCndpdGgodG1wLCB0LnRlc3QoYXMubnVtZXJpYyhgLVBpYCksIGFzLm51bWVyaWMoTW9jayksIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKd2l0aCh0bXAsIHdpbGNveC50ZXN0KGAtUGlgLCBNb2NrLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpCmBgYAoKPiBUaGVyZSBpcyBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgQVNSIGVmZmVjdCBpbiBjdGEx4oiGLCBidXQgdGhlIGVmZmVjdCBpcyB2ZXJ5IG1pbGQKCl8qKkNvbXBhcmluZyB0aGUgQVNSIGVmZmVjdCBpbiBjdGExzpQgdnMgd2lsZCB0eXBlKipfCgpVbnBhaXJlZCwgcmFuay1zdW0gdGVzdApgYGB7cn0KdG1wIDwtIGRhdC5mM3MxICU+JSAKICAjZmlsdGVyKEdlbm90eXBlID09ICJjdGExzpQiKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoSW5kZXgsIFN0cmFpbiwgR2Vub3R5cGUpLCBuYW1lc19mcm9tID0gUHJpbWFyeSwgdmFsdWVzX2Zyb20gPSByKSAlPiUgCiAgbXV0YXRlKEFTUiA9IGAtUGlgL01vY2spICU+JSAKICBhcnJhbmdlKEdlbm90eXBlKQoKdG1wICU+JSBncm91cF9ieShHZW5vdHlwZSkgJT4lIAogIHN1bW1hcml6ZShBU1Jfc2NvcmUgPSBwYXN0ZShyb3VuZChhcy5udW1lcmljKEFTUiksMSksIGNvbGxhcHNlID0gIiwgIiksIAogICAgICAgICAgICBtZWFuID0gbWVhbihBU1IpLCBzZCA9IHNkKEFTUikpCgprcnVza2FsLnRlc3QoYXMubnVtZXJpYyhBU1IpIH4gR2Vub3R5cGUsIGRhdGEgPSB0bXApCnBhaXJ3aXNlLndpbGNveC50ZXN0KHggPSBhcy5udW1lcmljKHRtcCRBU1IpLCBnID0gdG1wJEdlbm90eXBlLCBwYWlyZWQgPSBGQUxTRSwgcC5hZGp1c3QubWV0aG9kID0gIm5vbmUiKQpgYGAKIAo+IFRoZSB0ZXN0cyBvZiBpbnRlcmVzdHMgYW1vbmcgdGhlIHBhaXJ3aXNlIGNvbXBhcmlzb25zIGFyZSBiZXR3ZWVuIHRoZSB3aWxkIHR5cGUgYW5kIHRoZSBvdGhlciB0d28gc3RyYWlucwo+IEFwcGx5aW5nIEJvbmZlcnJvbmkgY29ycmVjdGlvbiB0byB0aGUgdHdvIHRlc3RzLCB3ZSBjb25jbHVkZSB0aGF0IF9jdGEx4oiGXyBpcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIHRoZSB3aWxkIHR5cGUKPiBpbiBpdHMgQVNSIGVmZmVjdCAoUCA9IDAuMDM0KSwgd2hpbGUgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBfY3RhMTo6Q1RBMV8gYW5kIHdpbGQgdHlwZSBpcyBub3QgKFAgPSAwLjQ4KS4KCiMjIyA2MCB2IDgwIHYgMi41IG1NCkEgc2Vjb25kIHNldCBvZiBjb25jZW50cmF0aW9ucwpgYGB7cn0KZGF0LmYzczIgPC0gZGF0LmYzcyAlPiUgCiAgbXV0YXRlKEdyb3VwID0gcGFzdGUoR2Vub3R5cGUsIEgyTzIsIHNlcCA9ICJfIikpICU+JSAKICAjZmlsdGVyKEgyTzIgJWluJSBjKCIxMDAgbU0iLCAiMyBtTSIpKSAlPiUgCiAgZmlsdGVyKEdyb3VwICVpbiUgYygid3RfNjAgbU0iLCAiQ2djdGExOjpDZ0NUQTFfODAgbU0iLCAiY3RhMTo6VVJBM18yLjUgbU0iKSkgJT4lIAogIHNlbGVjdCgtR3JvdXApICU+JSAKICBtdXRhdGUoCiAgICBQcmltYXJ5ID0gZmFjdG9yKFByaW1hcnksIGxldmVscyA9IGMoIk0iLCAiUCIpLCAKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTW9jayIsICItUGkiKSksCiAgICBHZW5vdHlwZSA9IGZhY3RvcihHZW5vdHlwZSwgbGV2ZWxzID0gYygid3QiLCAiQ2djdGExOjpDZ0NUQTEiLCAiY3RhMTo6VVJBMyIpLAogICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygid2lsZHR5cGUiLCAiY3RhMTo6Q1RBMSIsICJjdGExzpQiKSkpCiN3cml0ZV90c3YoZGF0LmYzYSwgZmlsZSA9ICIuLi9pbnB1dC8yMDIzMDUyMC1maWctM2QtZGF0YS1oYi50c3YiKQpgYGAKCiMjIyMgUGxvdApgYGB7cn0KcCA8LSBkYXQuZjNzMiAlPiUgCiAgbXV0YXRlKEdlbm90eXBlID0gZmN0X3JlY29kZShHZW5vdHlwZSwgIldUIiA9ICJ3aWxkdHlwZSIpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gUHJpbWFyeSwgeSA9IHIpKSArCiAgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBQcmltYXJ5KSwgc3Ryb2tlID0gMSwgc2l6ZSA9IDIsCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcigwLjEpKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKG5hbWUgPSAiIiwgdmFsdWVzID0gYygxLCAxNiksIGd1aWRlID0gIm5vbmUiKSArCiAgI3NjYWxlX2ZpbGxfbWFudWFsKG5hbWUgPSBicXVvdGUoSFsyXSpPWzJdKSwgdmFsdWVzID0gYygid2hpdGUiLCAiZ3JheTgwIikpICsKICBwLnN1cnZpdmFsWy0xXSArCiAgZmFjZXRfd3JhcCh+R2Vub3R5cGUgKyBIMk8yLCBucm93ID0gMSkgKwogIHBhbmVsX2JvcmRlcihjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpICsKICB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpCiAgICAgICAgKQpwCgpnZ3NhdmUoIi4uL291dHB1dC8yMDIzMDgwNi1maWczc3VwLWFzci1jdGExLWNvbXAtMi5wbmciLCB3aWR0aCA9IDUsIGhlaWdodCA9IDMpCmBgYAoKXyoqU3RhdGlzdGljYWwgdGVzdHMqKl8KCiMjIyMgU3RhdGlzdGljYWwgdGVzdAoxLiBEZXRlcm1pbmUgaWYgdGhlIGJhc2FsIHN1cnZpdmFsIHJhdGVzIGFyZSBkaWZmZXJlbnQgYmV0d2VlbiBnZW5vdHlwZXMgKFdpbGNveG9uIHNpZ25lZC1yYW5rIHRlc3QpCjEuIERldGVybWluZSBpZiB0aGUgcHJpbWFyeSBzdHJlc3MgZW5oYW5jZWQgdGhlIHN1cnZpdmFsIGluIF9lYWNoXyBnZW5vdHlwZSAoV2lsY294b24gc2lnbmVkLXJhbmsgdGVzdCkKCl8qKkJhc2FsIHN1cnZpdmFsIHJhdGUqKl8KCkJldHdlZW4gd3QgYW5kIGN0YTHiiIYsIHVucGFpcmVkLCByYW5rLXN1bSB0ZXN0LgpgYGB7cn0KdG1wIDwtIGRhdC5mM3MyICU+JSAKICBmaWx0ZXIoUHJpbWFyeSA9PSAiTW9jayIpICU+JSAKICBzZWxlY3QoSW5kZXgsIEdlbm90eXBlLCByKSAlPiUgCiAgbXV0YXRlKHIgPSBhcy5kb3VibGUocikpICU+JSAKICBhcnJhbmdlKEdlbm90eXBlKQoKdG1wICU+JSBncm91cF9ieShHZW5vdHlwZSkgJT4lIHN1bW1hcml6ZShtZWFuID0gbWVhbihyKSwgc2QgPSBudW0oc2QociksIGRpZ2l0cyA9IDMpKQoKa3J1c2thbC50ZXN0KHIgfiBHZW5vdHlwZSwgZGF0YSA9IHRtcCkKcGFpcndpc2Uud2lsY294LnRlc3QoeCA9IHRtcCRyLCBnID0gdG1wJEdlbm90eXBlKQpgYGAKCj4gYmFzYWwgc3Vydml2YWwgcmF0ZXMgbm90IHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGJldHdlZW4gZ2Vub3R5cGVzIGF0IHRoZSBjaG9zZW4gW0gyTzJdCgpfKipTdXJ2aXZhbCByYXRlIHdpdGggdGhlIHByaW1hcnkgc3RyZXNzKipfCgpCZXR3ZWVuIGdlbm90eXBlcywgdW5wYWlyZWQsIHJhbmstc3VtIHRlc3QuCmBgYHtyfQp0bXAgPC0gZGF0LmYzczIgJT4lIAogIGZpbHRlcihQcmltYXJ5ID09ICItUGkiKSAlPiUgCiAgc2VsZWN0KEluZGV4LCBHZW5vdHlwZSwgcikgJT4lIAogIGFycmFuZ2UoR2Vub3R5cGUpCgp0bXAgJT4lIGdyb3VwX2J5KEdlbm90eXBlKSAlPiUgc3VtbWFyaXplKG1lYW4gPSBtZWFuKHIpLCBzZCA9IG51bShzZChyKSwgZGlnaXRzID0gMykpCgprcnVza2FsLnRlc3QoYXMuZG91YmxlKHIpIH4gR2Vub3R5cGUsIGRhdGEgPSB0bXApCnBhaXJ3aXNlLndpbGNveC50ZXN0KHggPSB0bXAkciwgZyA9IHRtcCRHZW5vdHlwZSwgcGFpcmVkID0gRkFMU0UpCmBgYAo+IHN1cnZpdmFsIHJhdGVzIHdpdGggcHJpbWFyeSBzdHJlc3Mgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgYmV0d2VlbiBjdGEx4oiGIHZzIGVpdGhlciB0aGUgd2lsZHR5cGUgb3IgdGhlIGNvbXBsZW1lbnQuIE5vIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbGF0dGVyIHR3by4KCl8qKlByaW1hcnkgc3RyZXNzIGVuaGFuY2VkIGluIHdpbGR0eXBlKipfCgpDb21wYXJpc29uIGJldHdlZW4gciBhbmQgcicsIHBhaXJlZCwgc2lnbmVkLXJhbmsgdGVzdC4KYGBge3J9CnRtcCA8LSBkYXQuZjNzMiAlPiUgCiAgZmlsdGVyKEdlbm90eXBlID09ICJ3aWxkdHlwZSIpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhJbmRleCwgU3RyYWluKSwgbmFtZXNfZnJvbSA9IFByaW1hcnksIHZhbHVlc19mcm9tID0gcikgJT4lIAogIG11dGF0ZShBU1IgPSBgLVBpYC9Nb2NrKQoKdG1wCgp4IDwtIEhtaXNjOjpzbWVhbi5jbC5ib290KHRtcCRBU1IpCnNwcmludGYoIkFTUl9zY29yZSBtZWFuID0gJS4yZiwgOTUlJSBDSSBieSBib290c3RyYXAgPSBbJS4yZiwgJS4yZl0iLCB4WzFdLCB4WzJdLCB4WzNdKQoKd2l0aCh0bXAsIHQudGVzdChhcy5udW1lcmljKGAtUGlgKSwgYXMubnVtZXJpYyhNb2NrKSwgcGFpcmVkID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAiZyIpKQp3aXRoKHRtcCwgd2lsY294LnRlc3QoYC1QaWAsIE1vY2ssIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKYGBgCgpfKipQcmltYXJ5IHN0cmVzcyBlbmhhbmNlZCBpbiBDVEExIGNvbXBsZW1lbnQqKl8KCkNvbXBhcmlzb24gYmV0d2VlbiByIGFuZCByJywgcGFpcmVkLCBzaWduZWQtcmFuayB0ZXN0LgpgYGB7cn0KdG1wIDwtIGRhdC5mM3MyICU+JSAKICBmaWx0ZXIoR2Vub3R5cGUgPT0gImN0YTE6OkNUQTEiKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoSW5kZXgsIFN0cmFpbiksIG5hbWVzX2Zyb20gPSBQcmltYXJ5LCB2YWx1ZXNfZnJvbSA9IHIpICU+JSAKICBtdXRhdGUoQVNSID0gYC1QaWAvTW9jaykKCnRtcAoKeCA8LSBIbWlzYzo6c21lYW4uY2wuYm9vdCh0bXAkQVNSKQpzcHJpbnRmKCJBU1Jfc2NvcmUgbWVhbiA9ICUuMmYsIDk1JSUgQ0kgYnkgYm9vdHN0cmFwID0gWyUuMmYsICUuMmZdIiwgeFsxXSwgeFsyXSwgeFszXSkKCndpdGgodG1wLCB0LnRlc3QoYXMubnVtZXJpYyhgLVBpYCksIGFzLm51bWVyaWMoTW9jayksIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKd2l0aCh0bXAsIHdpbGNveC50ZXN0KGAtUGlgLCBNb2NrLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpCmBgYAoKXyoqUHJpbWFyeSBzdHJlc3MgZWZmZWN0IGluIGN0YTHOlCoqXwoKUGFpcmVkLCBzaWduZWQtcmFuayB0ZXN0CmBgYHtyfQp0bXAgPC0gZGF0LmYzczIgJT4lIAogIGZpbHRlcihHZW5vdHlwZSA9PSAiY3RhMc6UIikgJT4lIAogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKEluZGV4LCBTdHJhaW4pLCBuYW1lc19mcm9tID0gUHJpbWFyeSwgdmFsdWVzX2Zyb20gPSByKSAlPiUgCiAgbXV0YXRlKEFTUiA9IGAtUGlgL01vY2spCgp0bXAKCnggPC0gSG1pc2M6OnNtZWFuLmNsLmJvb3QodG1wJEFTUikKc3ByaW50ZigiQVNSX3Njb3JlIG1lYW4gPSAlLjJmLCA5NSUlIENJIGJ5IGJvb3RzdHJhcCA9IFslLjJmLCAlLjJmXSIsIHhbMV0sIHhbMl0sIHhbM10pCgp3aXRoKHRtcCwgdC50ZXN0KGFzLm51bWVyaWMoYC1QaWApLCBhcy5udW1lcmljKE1vY2spLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpCndpdGgodG1wLCB3aWxjb3gudGVzdChgLVBpYCwgTW9jaywgcGFpcmVkID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAiZyIpKQpgYGAKPiBBU1IgZWZmZWN0IG5vdCBzaWduaWZpY2FudCBpbiBjdGEx4oiGLgoKXyoqQ29tcGFyaW5nIHRoZSBBU1IgZWZmZWN0IGluIGN0YTHOlCB2cyB3aWxkIHR5cGUqKl8KClVucGFpcmVkLCByYW5rLXN1bSB0ZXN0CmBgYHtyfQp0bXAgPC0gZGF0LmYzczIgJT4lIAogICNmaWx0ZXIoR2Vub3R5cGUgPT0gImN0YTHOlCIpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhJbmRleCwgU3RyYWluLCBHZW5vdHlwZSksIG5hbWVzX2Zyb20gPSBQcmltYXJ5LCB2YWx1ZXNfZnJvbSA9IHIpICU+JSAKICBtdXRhdGUoQVNSID0gYC1QaWAvTW9jaykgJT4lIAogIGFycmFuZ2UoR2Vub3R5cGUpCgp0bXAgJT4lIGdyb3VwX2J5KEdlbm90eXBlKSAlPiUgCiAgc3VtbWFyaXplKEFTUl9zY29yZSA9IHBhc3RlKHJvdW5kKGFzLm51bWVyaWMoQVNSKSwxKSwgY29sbGFwc2UgPSAiLCAiKSwgCiAgICAgICAgICAgIG1lYW4gPSBtZWFuKEFTUiksIHNkID0gc2QoQVNSKSkKCmtydXNrYWwudGVzdChhcy5udW1lcmljKEFTUikgfiBHZW5vdHlwZSwgZGF0YSA9IHRtcCkKcGFpcndpc2Uud2lsY294LnRlc3QoeCA9IGFzLm51bWVyaWModG1wJEFTUiksIGcgPSB0bXAkR2Vub3R5cGUsIHBhaXJlZCA9IEZBTFNFLCBwLmFkanVzdC5tZXRob2QgPSAibm9uZSIpCmBgYAoKPiBUaGUgdGVzdHMgb2YgaW50ZXJlc3RzIGFtb25nIHRoZSBwYWlyd2lzZSBjb21wYXJpc29ucyBhcmUgYmV0d2VlbiB0aGUgd2lsZCB0eXBlIGFuZCB0aGUgb3RoZXIgdHdvIHN0cmFpbnMKPiBBcHBseWluZyBCb25mZXJyb25pIGNvcnJlY3Rpb24gdG8gdGhlIHR3byB0ZXN0cywgd2UgY29uY2x1ZGUgdGhhdCBfY3RhMeKIhl8gaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSB0aGUgd2lsZCB0eXBlCj4gaW4gaXRzIEFTUiBlZmZlY3QgKFAgPSAwLjAwNDQpLCB3aGlsZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIF9jdGExOjpDVEExXyBhbmQgd2lsZCB0eXBlIGlzIG5vdCAoUCA9IDEpLgoKIyMgRmlnNjogQVNSIGluIHJpbTE14oiGIHZzIHd0Cl8qKkdvYWwqKl8KCkRldGVybWluZSBpZiBSaW0xNSBpcyBwYXJ0IG9mIHRoZSBzaWduYWxpbmcgbmV0d29yayBiZWhpbmQgdGhlIEFTUi4KCl8qKlJhdGlvbmFsZSoqXwoKUmltMTUgaXMgdGhlIHllYXN0IGhvbW9sb2cgb2YgdGhlIEdyZWF0d2FsbCBraW5hc2UsIHJlZ3VsYXRpbmcgbXVsdGlwbGUgZG93bnN0cmVhbSBwcm9jZXNzZXMgYW5kIGlzIGl0c2VsZiByZWd1bGF0ZWQgYnkgYXQgbGVhc3QgdGhyZWUgbWFqb3Iga2luYXNlIGNvbXBsZXhlcy4gVGhpcyBwdXRzIGl0IGF0IGEgY3Jvc3Nyb2FkIG9mIHNpZ25hbCBpbnRlZ3JhdGlvbi4gT25lIG9mIHRoZSB1cHN0cmVhbSBraW5hc2VzIHJlZ3VsYXRpbmcgUmltMTUgaXMgVE9SQzEsIHdoaWNoIHdlIGxhdGVyIGZvdW5kIHRvIGJlIGNvbm5lY3RlZCB3aXRoIHRoZSBBU1IuCgpfKipEYXRhKipfCgpTcGVjaWVzICAgICAgIFN0cmFpbiAgICAgICAgICAgR2Vub3R5cGUgICAgIEgyTzIgICAgICAgICAKLS0tLS0tLS0gICAgICAtLS0tLS0tLS0tLS0tICAgIC0tLS0tLS0tLS0gICAtLS0tLS0tLS0tLS0KQy4gZ2xhYnJhdGEgICB5SDAwMSwgeUgwMDIgICAgIHdpbGR0eXBlICAgICA4MCwgMTAwIG1NIApDLiBnbGFicmF0YSAgIHlINjA5LCB5SDYxMCAgICAgX3JpbTE14oiGXyAgICAgNjAsICA4MCBtTSAKCkVpZ2h0IHJlcGxpY2F0ZXMgKGF0IHR3byBbSDJPMl0pLCB0d28gZWFjaCBmcm9tIDA2LzI4LCAwNi8yOSBhbmQgMDcvMTMsIHBsdXMgb25lIGVhY2ggZnJvbSAwNy8wMiBhbmQgMDcvMDQgb2YgMjAyMi4gVGhlIGRhdGEgZnJvbSA3LzQgc2hvdWxkIGJlIGV4Y2x1ZGVkIGJlY2F1c2UgSmlueWUgbm90ZWQgbWVkaWEgY29udGFtaW5hdGlvbiBvbiB0aGF0IGRheS4KCiMjIyBEYXRhIHJlZm9ybWF0dGluZwpSZWZvcm1hdCBKWSdzIGRhdGEgaW50byBhIHRpZHkgZm9ybWF0LiBOb3RlIHRoYXQgdGhlIGZvbGxvd2luZyBkYXRhIGZpbGUgY29udGFpbnMgdGhlIHNhbWUgaW5mb3JtYXRpb24gYXMgaW4gdGhlIGByYXdgIG9iamVjdCBpbXBvcnRlZCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoaXMgcm1hcmtkb3duLiBUaGUgZmlsZSBiZWxvdywgaG93ZXZlciwgY29udGFpbnMgZXhwZXJpbWVudGFsIG5vdGVzLCBpbmNsdWRpbmcgNy80LzIyIGRhdGEgaGF2aW5nIG1lZGlhIGNvbnRhbWluYXRpb24gaXNzdWVzLgpgYGB7cn0KdG1wIDwtIHJlYWRfdHN2KCIuLi9pbnB1dC8yMDIzMDUyMi1yaW0xNS1kYXRhLWp5LnRzdiIsIGNvbF90eXBlcyA9IGNvbHMoKSwgY29tbWVudCA9ICIjIikgJT4lIAogIG11dGF0ZShEYXRlID0gZ3N1YigiKFxcZFxcZCkoXFxkXFxkKShcXGRcXGQpIiwgIlxcMS9cXDIvXFwzIiwgRGF0ZSkpICU+JSAKICBzZWxlY3QoLWBNTy9NTV9wZXJjZW50YCwgLWBQTy9QTV9wZXJjZW50YCkKCiMgZGF0YSBzYW5pdHkgY2hlY2ssIHF1aWNrIHZpZXcKc2FwcGx5KHNlbGVjdCh0bXAsIERhdGUsIFNwZWNpZXMsIFN0cmFpbiwgR2Vub3R5cGUsIExlbl8xLCBMZW5fMiwgSDJPMiksIHVuaXF1ZSkKCmRhdC5mNmIgPC0gdG1wICU+JSAKICBwaXZvdF9sb25nZXIoYyhDb3VudF9NT19NTSwgQ291bnRfUE9fUE0pLCBuYW1lc190byA9ICJQcmltYXJ5IiwgdmFsdWVzX3RvID0gIkNvdW50IikgJT4lIAogIG11dGF0ZShQcmltYXJ5ID0gZmN0X3JlY29kZShQcmltYXJ5LCAiTW9jayIgPSAiQ291bnRfTU9fTU0iLCAiLVBpIiA9ICJDb3VudF9QT19QTSIpLAogICAgICAgICBzY2FsZWQgPSBDb3VudCAqIERpbHV0aW9ucyAqIDFlLTMpICU+JSAKICBncm91cF9ieShEYXRlLCBTdHJhaW4sIEdlbm90eXBlLCBQcmltYXJ5KSAlPiUKICBtdXRhdGUoc2NhbGVkX00gPSBzY2FsZWRbSDJPMiA9PSAiMCBtTSJdLAogICAgICAgICByID0gc2NhbGVkIC8gc2NhbGVkX00pICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgc2VsZWN0KERhdGUsIFNwZWNpZXMsIFN0cmFpbiwgR2Vub3R5cGUsIFByaW1hcnksIEgyTzIsIERpbHV0aW9ucywgCiAgICAgICAgIENvdW50LCBzY2FsZWQsIHNjYWxlZF9NLCByLCBQcmlzbV9kYXRhX3BvaW50LCBOb3RlKSAlPiUgCiAgYXJyYW5nZShEYXRlLCBHZW5vdHlwZSwgUHJpbWFyeSkKYGBgClNhdmUgdGhlIGRhdGEgZm9yIGZ1dHVyZSByZWZlcmVuY2VzCmBgYHtyfQp3cml0ZV90c3YoZGF0LmY2YiwgZmlsZSA9ICIuLi9pbnB1dC8yMDIzMDUyMy1maWctNi1kYXRhLWhiLnRzdiIpCmBgYAoKQmVsb3cgdGhlIHNhbWUgZGF0YSBpcyBleHRyYWN0ZWQgZnJvbSB0aGUgbGFyZ2UgZGF0YXNldC4gVGhlIGNvdW50IGluZm9ybWF0aW9uIHNob3VsZCBiZSB0aGUgc2FtZS4KYGBgCnVzZS5mNiA8LSBwYXN0ZTAoYygiMDYvMjgiLCAiMDYvMjkiLCAiMDcvMDIiLCAiMDcvMTMiKSwgIi8yMiIpCnRtcCA8LSAgcmF3ICU+JQogIGZpbHRlcihEYXRlICVpbiUgdXNlLmY2KSAlPiUgCiAgbXV0YXRlKAogICAgc2NhbGVkID0gQ291bnQgKiBEaWx1dGlvbnMgKiAxZS0yCiAgKSAlPiUgCiAgIyByZW1vdmUgdW5pbmZvcm1hdGl2ZSBjb2x1bW5zLiBvbmx5IG9uZSBIMk8yIGNvbmMgdXNlZCBmb3IgZWFjaCBzcGVjaWVzCiAgc2VsZWN0KC1MZW5fMSwgLUxlbl8yLCAtRXhwZXJpbWVudGVyKQojIEFzc3VtZSB0aGUgcmVwbGljYXRlcyB3ZXJlIHBhaXJlZCBpbiB0aGUgb3JkZXIgdGhleSBhcHBlYXIgaW4gdGhlIHRhYmxlLAojIGkuZS4sIHRoZSBmaXJzdCByb3cgaW4gdGhlIE1PLCBNTSwgUE8sIFBNIGdyb3VwcyBiZWxvbmcgdG8gdGhlIHNhbWUgYmlvbG9naWNhbCAKIyByZXBsaWNhdGUsIHdlIGNhbiBkZXJpdmUgdGhyZWUgQVNSX3Njb3JlcyBmb3IgZWFjaCBkYXRlIHggc3BlY2llcyB4IExlbl8xCgpkYXQuZjYgPC0gdG1wICU+JSAKICAjIGdyb3VwIGJ5IHByaW1hcnkgdG8gY2FsY3VsYXRlIHIgKE1PL01NKSBvciByJyAoUE8vUE0pCiAgc2VwYXJhdGUoR3JvdXAsIGludG8gPSBjKCJQcmltYXJ5IiwgIlNlY29uZGFyeSIpLCBzZXAgPSAxKSAlPiUgCiAgZ3JvdXBfYnkoRGF0ZSwgU3RyYWluLCBQcmltYXJ5KSAlPiUgCiAgIyBjYWxjdWxhdGUgJSBzdXJ2aXZhbAogIG11dGF0ZShzY2FsZWRfTSA9IHNjYWxlZFtTZWNvbmRhcnkgPT0gIk0iXSwKICAgICAgICAgciA9IHNjYWxlZCAvIHNjYWxlZFtTZWNvbmRhcnkgPT0gIk0iXSkgJT4lIAogICMgcmVtb3ZlIHRoZSBzZWNvbmRhcnkgbW9jayBhcyB0aGUgaW5mb3JtYXRpb24gYXJlIGFsbCB1c2VkCiAgZmlsdGVyKFNlY29uZGFyeSAhPSAiTSIpCmRhdC5mNgpgYGAKCiMjIyBQbG90IChhbGwgZGF0YSkKQW5ub3RhdGUgdGhlIGRhdGEuIEZvciA3LzIgYW5kIDcvNCBkYXRhLCBvbmx5IHVzZSB5SDAwMSBmb3IgdGhlIHd0LCBzbyB3ZSBlbmQgdXAgd2l0aCB0aGUgc2FtZSBudW1iZXIgb2YgcmVwbGljYXRlcyBmb3IgYm90aCBzdHJhaW5zLgpgYGB7cn0KZGF0LmY2cCA8LSBkYXQuZjZiICU+JSAKICBmaWx0ZXIoSDJPMiAhPSAiMCBtTSIsIAogICAgICAgICAhKERhdGUgPT0gIjA3LzAyLzIyIiAmIFN0cmFpbiA9PSAieUgwMDIiKSwgRGF0ZSAhPSAiMDcvMDQvMjIiKSAlPiUgCiAgbXV0YXRlKAogICAgR2Vub3R5cGUgPSBmYWN0b3IoR2Vub3R5cGUsIGxldmVscyA9IGMoInd0IiwgInJpbTE1zpQiKSksCiAgICBncm91cCA9IHBhc3RlKEdlbm90eXBlLCBnc3ViKCIgIiwgIiIsIEgyTzIpLCBzZXAgPSAiXyIpLAogICAgU2Vjb25kYXJ5ID0gZmFjdG9yKGdyb3VwLCAKICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJ3dF8xMDBtTSIsICJ3dF84MG1NIiwgInJpbTE1zpRfODBtTSIsICJyaW0xNc6UXzYwbU0iKSwKICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJIaWdoIiwgIk1lZGl1bSIsICJIaWdoIiwgIk1lZGl1bSIpKQogICkKd2l0aChkYXQuZjZwLCB0YWJsZShEYXRlLCBncm91cCkpCmBgYAoKYGBge3J9CmRhdC5mNnAgJT4lCiAgZ2dwbG90KGFlcyh4ID0gSDJPMiwgeSA9IHIpKSArICNwLnN1cnZpdmFsWy0zXSArCiAgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBQcmltYXJ5KSwgc3Ryb2tlID0gMSwgc2l6ZSA9IDIsIAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAwLjIsIGRvZGdlLndpZHRoID0gMC45KSkgKwogIHN0YXRfc3VtbWFyeShhZXMoZ3JvdXAgPSBQcmltYXJ5KSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpLAogICAgICAgICAgICAgICBmdW4gPSBtZWFuLCBmdW4ubWF4ID0gbWVhbiwgZnVuLm1pbiA9IG1lYW4sCiAgICAgICAgICAgICAgIGdlb20gPSAiY3Jvc3NiYXIiLCBjb2xvciA9ICJyZWQiLCB3aWR0aCA9IDAuNSkgKwogIGZhY2V0X3dyYXAofiBTZWNvbmRhcnkgKyBHZW5vdHlwZSwgbnJvdyA9IDEsIHNjYWxlcyA9ICJmcmVlX3giKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoIk1vY2siID0gMSwgIi1QaSIgPSAxNikpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50KSArCiAgeGxhYihicXVvdGUoSFsyXSpPWzJdfihtTSkpKSArIHlsYWIoIiUgc3Vydml2YWwiKSArCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTQsIGJhc2VfbGluZV9zaXplID0gMSkgKwogIHBhbmVsX2JvcmRlcihjb2xvciA9ICJibGFjayIsIHNpemUgPSAxKSArCiAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDEpLCBmYWNlID0gMyksCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkKYGBgCgojIyMgQmFzYWwgc3Vydml2YWwgcmF0ZXMKClN0YXRpc3RpY2FsIHRlc3QgZm9yIGRpZmZlcmVuY2VzIGluIGJhc2FsIHN1cnZpdmFsIGJldHdlZW4gZ2Vub3R5cGVzLiBJIGZpcnN0IGFwcGxpZWQgdGhlIEtydXNrYWwtV2FsbGlzIHRlc3QsIHdoaWNoIGlzIGFuIGV4dGVuc2lvbiBvZiB0aGUgTWFubi1XaGl0bmV5J3MgVSB0ZXN0IGZvciBtdWx0aXBsZSBncm91cHMgYW5kIGlzIGVxdWl2YWxlbnQgdG8gQU5PVkEgYnV0IGFwcGxpZWQgb24gcmFua3MuIEkgdXNlZCB0aGlzIHRlc3QgdG8gZGV0ZXJtaW5lIGlmIHRoZXJlIGlzIGV2aWRlbmNlIGZvciBkaWZmZXJlbmNlcyBpbiB0aGUgYmFzYWwgc3Vydml2YWwgcmF0ZXMgYW1vbmcgdGhlIGZvdXIgZ3JvdXBzICgyIGdlbm90eXBlcyB4IDIgW0gyTzJdKS4KCmBgYHtyfQp0bXAgPC0gZGF0LmY2cCAlPiUgZmlsdGVyKFByaW1hcnkgPT0gIk1vY2siKQp0bXAgJT4lIGdyb3VwX2J5KGdyb3VwKSAlPiUgCiAgc3VtbWFyaXplKAogICAgdGVzdCA9IEhtaXNjOjpzbWVhbi5jbC5ub3JtYWwocikgJT4lIHQoKSAlPiUgYXNfdGliYmxlKCkKICApICU+JSAKICB1bm5lc3QodGVzdCkgJT4lIAogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMuZG91YmxlKSwgcm91bmQsIGRpZ2l0cyA9IDMpKQprcnVza2FsLnRlc3QociB+IGdyb3VwLCBkYXRhID0gdG1wKQpgYGAKPiBUaGVyZSBhcmUgZGlmZmVyZW5jZXMgYW1vbmcgdGhlIGZvdXIgZ3JvdXBzLiBJbnNwZWN0aW5nIHRoZSBzdGF0aXN0aWNhbCBzdW1tYXJ5LCB3ZSBjYW4gc2VlIHRoYXQgdGhlIGhpZ2ggYW5kIGxvdyBjb25jZW50cmF0aW9ucyB1c2VkIGZvciBlYWNoIGdlbm90eXBlIHNlZW0gdG8gbWF0Y2ggZWFjaCBvdGhlciB3ZWxsLgo+IFRoZXJlZm9yZSwgd2Ugd2lsbCBuZXh0IHVzZSBBIFdpbGNveG9uIHJhbmstc3VtIHRlc3QgdG8gY29tcGFyZSB0aGUgdHdvIGdlbm90eXBlcyBhdCBlaXRoZXIgdGhlIGhpZ2ggb3IgdGhlIGxvdyBkb3NlCgpTdGF0aXN0aWNhbCB0ZXN0IGZvciBkaWZmZXJlbmNlcyBpbiBiYXNhbCBzdXJ2aXZhbCBiZXR3ZWVuIGdlbm90eXBlcyBhdCAxMDAgLyA4MCBtTS4KYGBge3J9CnRtcCA8LSBkYXQuZjZwICU+JSAKICBmaWx0ZXIoZ3JvdXAgJWluJSBjKCJ3dF8xMDBtTSIsICJyaW0xNc6UXzgwbU0iKSwgUHJpbWFyeSA9PSAiTW9jayIpCndpbGNveC50ZXN0KHIgfiBncm91cCwgZGF0YSA9IHRtcCwgcGFpcmVkID0gRkFMU0UpCmBgYAoKU3RhdGlzdGljYWwgdGVzdCBmb3IgZGlmZmVyZW5jZXMgaW4gYmFzYWwgc3Vydml2YWwgYmV0d2VlbiBnZW5vdHlwZXMgYXQgODAvNjAgbU0uCmBgYHtyfQp0bXAgPC0gZGF0LmY2cCAlPiUgCiAgZmlsdGVyKGdyb3VwICVpbiUgYygid3RfODBtTSIsICJyaW0xNc6UXzYwbU0iKSwgUHJpbWFyeSA9PSAiTW9jayIpCndpbGNveC50ZXN0KHIgfiBncm91cCwgZGF0YSA9IHRtcCwgcGFpcmVkID0gRkFMU0UpCmBgYAo+IHllcywgdGhlIHN1cnZpdmFsIHJhdGVzIGFyZSBjb21wYXJhYmxlIGJldHdlZW4gc3BlY2llcyBhdCB0aGUgdHdvIHBhaXJzIG9mIGNob3NlbiBbSDJPMl0KPiBXZSBjYW4gY29uY2x1ZGUgdGhhdCB0aGVyZSBpcyBubyBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIHN1cnZpdmFsIHdoZW4gY29tcGFyaW5nIDEwMCBtTSB2cyA4MCBtTSBmb3Igd3QgYW5kIHJpbTE14oiGLiBTaW1pbGFybHksIHRoZXJlIGlzIG5vIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgaW4gc3Vydml2YWwgd2hlbiA4MCBtTSBhbmQgNjAgbU0gd2VyZSB1c2VkIHRvIHRyZWF0IHRoZSB0d28gc3RyYWlucywgcmVzcGVjdGl2ZWx5LgoKIyMjIDEwMCB2cyA4MCBtTQojIyMjIFBsb3QKYGBge3J9CmRhdC5mNnAgJT4lIGZpbHRlcihTZWNvbmRhcnkgPT0gIkhpZ2giKSAlPiUgCiAgbXV0YXRlKEdlbm90eXBlID0gZmN0X3JlY29kZShHZW5vdHlwZSwgYFdUYCA9ICJ3dCIpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gUHJpbWFyeSwgeSA9IHIpKSArIAogICNnZW9tX2xpbmUoYWVzKGdyb3VwID0gcGFzdGUwKERhdGUsIFN0cmFpbiwgU2Vjb25kYXJ5KSksCiAgIyAgICAgICAgICBsaW5ldHlwZSA9IDIsIGxpbmV3aWR0aCA9IDAuMSkgKyAKICBnZW9tX3BvaW50KGFlcyhzaGFwZSA9IFByaW1hcnkpLCBzdHJva2UgPSAxLCBzaXplID0gMiwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKDAuMDUpKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoMSwgMTYpLCBndWlkZSA9ICJub25lIikgKwogIHAuc3Vydml2YWxbLTFdICsKICBmYWNldF93cmFwKH5HZW5vdHlwZSArIEgyTzIsIG5yb3cgPSAxKSArCiAgcGFuZWxfYm9yZGVyKGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEuNSkgKwogIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSAiY2VudGVyIiwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDAuOSkpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDAuOSkpKQojZ2dzYXZlKCIuLi9vdXRwdXQvMjAyMzA1MjItcmltMTUtdnMtd3QtQVNSLnBuZyIsIHdpZHRoID0gMy42LCBoZWlnaHQgPSAzLjQpCmBgYAoKIyMjIyBTdGF0aXN0aWNhbCB0ZXN0CjEuIERldGVybWluZSBpZiB0aGUgYmFzYWwgc3Vydml2YWwgcmF0ZXMgYXJlIGRpZmZlcmVudCBiZXR3ZWVuIHd0IGFuZCBjdGEx4oiGIChXaWxjb3hvbiBzaWduZWQtcmFuayB0ZXN0KQoxLiBEZXRlcm1pbmUgaWYgdGhlIHByaW1hcnkgc3RyZXNzIGVuaGFuY2VkIHRoZSBzdXJ2aXZhbCBpbiBfZWFjaF8gZ2Vub3R5cGUgKFdpbGNveG9uIHNpZ25lZC1yYW5rIHRlc3QpCgpfKipCYXNhbCBzdXJ2aXZhbCByYXRlKipfCgpSZXBlYXRpbmcgdGhlIHRlc3QgYWJvdmU6CgpTdGF0aXN0aWNhbCB0ZXN0IGZvciBkaWZmZXJlbmNlcyBpbiBiYXNhbCBzdXJ2aXZhbCBiZXR3ZWVuIGdlbm90eXBlcyBhdCAxMDAgLyA4MCBtTS4KYGBge3J9CnRtcCA8LSBkYXQuZjZwICU+JSAKICBmaWx0ZXIoU2Vjb25kYXJ5ID09ICJIaWdoIiwgUHJpbWFyeSA9PSAiTW9jayIpCndpbGNveC50ZXN0KHIgfiBHZW5vdHlwZSwgZGF0YSA9IHRtcCwgcGFpcmVkID0gRkFMU0UpCmBgYAoKX0FTUiBpbiB3aWxkdHlwZV8KCkNvbXBhcmlzb24gYmV0d2VlbiByIGFuZCByJywgcGFpcmVkLCBzaWduZWQtcmFuayB0ZXN0LgpgYGB7cn0KdG1wIDwtIGRhdC5mNnAgJT4lIGZpbHRlcihTZWNvbmRhcnkgPT0gIkhpZ2giKSAlPiUgIAogIGZpbHRlcihHZW5vdHlwZSA9PSAid3QiKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoRGF0ZSwgU3RyYWluLCBIMk8yKSwgbmFtZXNfZnJvbSA9IFByaW1hcnksIHZhbHVlc19mcm9tID0gcikgJT4lIAogIG11dGF0ZShBU1IgPSBgLVBpYC9Nb2NrKQoKdG1wCgp4IDwtIEhtaXNjOjpzbWVhbi5jbC5ib290KHRtcCRBU1IpCnNwcmludGYoIkFTUl9zY29yZSBtZWFuID0gJS4yZiwgOTUlJSBDSSBieSBib290c3RyYXAgPSBbJS4yZiwgJS4yZl0iLCB4WzFdLCB4WzJdLCB4WzNdKQoKd2l0aCh0bXAsIHQudGVzdChhcy5udW1lcmljKGAtUGlgKSwgYXMubnVtZXJpYyhNb2NrKSwgcGFpcmVkID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAiZyIpKQp3aXRoKHRtcCwgd2lsY294LnRlc3QoYC1QaWAsIE1vY2ssIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKYGBgCgpfQVNSIGluIHJpbTE1zpRfCgpQYWlyZWQsIHNpZ25lZC1yYW5rIHRlc3QKYGBge3J9CnRtcCA8LSBkYXQuZjZwICU+JSBmaWx0ZXIoU2Vjb25kYXJ5ID09ICJIaWdoIikgJT4lCiAgZmlsdGVyKEdlbm90eXBlID09ICJyaW0xNc6UIikgJT4lIAogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKERhdGUsIFN0cmFpbiwgSDJPMiksIG5hbWVzX2Zyb20gPSBQcmltYXJ5LCB2YWx1ZXNfZnJvbSA9IHIpICU+JSAKICBtdXRhdGUoQVNSID0gYC1QaWAvTW9jaykKCnRtcAoKeCA8LSBIbWlzYzo6c21lYW4uY2wuYm9vdCh0bXAkQVNSKQpzcHJpbnRmKCJBU1Jfc2NvcmUgbWVhbiA9ICUuMmYsIDk1JSUgQ0kgYnkgYm9vdHN0cmFwID0gWyUuMmYsICUuMmZdIiwgeFsxXSwgeFsyXSwgeFszXSkKCndpdGgodG1wLCB0LnRlc3QoYXMubnVtZXJpYyhgLVBpYCksIGFzLm51bWVyaWMoTW9jayksIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKd2l0aCh0bXAsIHdpbGNveC50ZXN0KGAtUGlgLCBNb2NrLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpCmBgYAoKXyoqQVNSIGVmZmVjdCBzaXplIGJldHdlZW4gd3QgYW5kIHJpbTE14oiGKipfCgpgYGB7cn0KdG1wIDwtIGRhdC5mNnAgJT4lIAogIGZpbHRlcihTZWNvbmRhcnkgPT0gIkhpZ2giKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoRGF0ZSwgU3RyYWluLCBHZW5vdHlwZSksIG5hbWVzX2Zyb20gPSBQcmltYXJ5LCB2YWx1ZXNfZnJvbSA9IHIpICU+JSAKICBtdXRhdGUoQVNSID0gYC1QaWAvTW9jaykgJT4lIAogIGFycmFuZ2UoR2Vub3R5cGUpCgp0bXAgJT4lIGdyb3VwX2J5KEdlbm90eXBlKSAlPiUgCiAgc3VtbWFyaXplKEFTUl9zY29yZSA9IHBhc3RlKHJvdW5kKGFzLm51bWVyaWMoQVNSKSwxKSwgY29sbGFwc2UgPSAiLCAiKSwgCiAgICAgICAgICAgIG1lYW4gPSBtZWFuKEFTUiksIHNkID0gc2QoQVNSKSkKCnQudGVzdChhcy5udW1lcmljKEFTUikgfiBHZW5vdHlwZSwgcGFpcmVkID0gRkFMU0UsIGRhdGEgPSB0bXApCndpbGNveC50ZXN0KGFzLm51bWVyaWMoQVNSKSB+IEdlbm90eXBlLCBwYWlyZWQgPSBGQUxTRSwgZGF0YSA9IHRtcCkKYGBgCgo+IFRoZSBkaWZmZXJlbmNlIGluIHRoZSBBU1Itc2NvcmUgYmV0d2VlbiBfcmltMTXiiIZfIGFuZCB3aWxkIHR5cGUgaXMgc2lnbmlmaWNhbnQgYXQgYSAwLjA1IGxldmVsIChQID0gMC4wNCkuCgojIyBGaWc2LVMxOiBSSU0xNSBjb21wbGVtZW50YXRpb24KXyoqR29hbCoqXwoKLSBWYWxpZGF0ZSB0aGF0IF9yaW0xNeKIhl8gcmVzdWx0IGlzIGR1ZSB0byB0aGUgaW50ZW5kZWQgZGVsZXRpb24KCl8qKkV4cGVyaW1lbnQqKl8KCi0gQmluIGNvbnN0cnVjdGVkIGEgX1JJTTE1XyBjb21wbGVtZW50YXRpb24gc3RyYWluIGJ5IHB1dHRpbmcgdGhlIGdlbmUncyBDRFMgYmFjayB0byBpdHMgZW5kb2dlbm91cyBsb2N1cy4gCi0gSGFueGkgcGVyZm9ybWVkIEFTUiB0byBjb21wYXJlIHRoZSBBU1IgZWZmZWN0IHNpemUgb2YgdGhlIGNvbXBsZW1lbnRhdGlvbiwgdGhlIGRlbGV0aW9uIGFuZCB0aGUgd2lsZCB0eXBlLgoKXyoqRGF0YSoqXwoKU3BlY2llcyAgICAgICBTdHJhaW4gICAgICAgICAgR2Vub3R5cGUgICAgICAgSDJPMiAgICAgICAgIAotLS0tLS0tLSAgICAgIC0tLS0tLS0tLS0tLS0gICAtLS0tLS0tLS0tLS0gICAtLS0tLS0tLS0tLS0tLQpDLiBnbGFicmF0YSAgIHlIMDAxLDAwMiAgICAgICB3aWxkdHlwZSAgICAgICA2MCwgODAsIDEwMCBtTSAKQy4gZ2xhYnJhdGEgICB5SDYwOSw2MTAgICAgICAgX3JpbTUx4oiGXyAgICAgICA2MCwgODAsIDEwMCBtTQpDLiBnbGFicmF0YSAgIHlINzMxLDczMiAgICAgICByaW0xNTo6UklNMTUgICA2MCwgODAsIDEwMCBtTQoKRXhwZXJpbWVudHMgYmV0d2VlbiA4LzgvMjMgLSA4LzEwLzIzCgpfKipBbmFseXNpcyoqXwoKIyMjIFJlYWQgYW5kIGZvcm1hdCBkYXRhCmBgYHtyfQp0bXAgPC0gcmVhZF90c3YoIi4uL2lucHV0LzIwMjMwODA4LXJpbTE1LWNvbXBsZW1lbnQtZGF0YS1odC50c3YiLAogICAgICAgICAgICAgICAgY29sX3R5cGVzID0gY29scygpLCBjb21tZW50ID0gIiMiKSAlPiUgCiAgbXV0YXRlKAogICAgc2NhbGVkID0gQ291bnQgKiBEaWx1dGlvbnMgKiAxZS0yCiAgKQoKZGF0LmY2cyA8LSB0bXAgJT4lIAogICMgcmVtb3ZlIHVuaW5mb3JtYXRpdmUgY29sdW1ucy4gb25seSBvbmUgSDJPMiBjb25jIHVzZWQgZm9yIGVhY2ggc3BlY2llcwogIHNlbGVjdCgtTGVuXzEsIC1MZW5fMiwgLVNwZWNpZXMpICU+JSAKICAjIGdyb3VwIGJ5IGV4cGVyaW1lbnQgYW5kIEgyTzIgdG8gY2FsY3VsYXRlIHIgKE1PL01NKSBvciByJyAoUE8vUE0pCiAgc2VwYXJhdGUoR3JvdXAsIGludG8gPSBjKCJQcmltYXJ5IiwgIlNlY29uZGFyeSIpLCBzZXAgPSAxKSAlPiUgCiAgZ3JvdXBfYnkoRGF0ZSwgU3RyYWluLCBQcmltYXJ5KSAlPiUgCiAgIyBjYWxjdWxhdGUgJSBzdXJ2aXZhbAogIG11dGF0ZShzY2FsZWRfTSA9IHNjYWxlZFtTZWNvbmRhcnkgPT0gIk0iXSwKICAgICAgICAgciA9IG51bShzY2FsZWQgLyBzY2FsZWRbU2Vjb25kYXJ5ID09ICJNIl0sIGRpZ2l0cyA9IDMpKSAlPiUgCiAgIyByZW1vdmUgdGhlIHNlY29uZGFyeSBtb2NrIGFzIHRoZSBpbmZvcm1hdGlvbiBhcmUgYWxsIHVzZWQKICBmaWx0ZXIoU2Vjb25kYXJ5ICE9ICJNIikgJT4lIAogIG11dGF0ZSgKICAgIFByaW1hcnkgPSBmYWN0b3IoUHJpbWFyeSwgbGV2ZWxzID0gYygiTSIsICJQIiksIAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJNb2NrIiwgIi1QaSIpKSwKICAgIEdlbm90eXBlID0gZmFjdG9yKEdlbm90eXBlLCBsZXZlbHMgPSBjKCJ3dCIsICJyaW0xNTo6UklNMTUiLCAicmltMTU6OkhpczMiKSwKICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIndpbGR0eXBlIiwgInJpbTE1OjpSSU0xNSIsICJyaW0xNc6UIikpLAogICAgSDJPMiA9IGZhY3RvcihIMk8yLCBsZXZlbHMgPSBjKCI2MCBtTSIsICI4MCBtTSIsICIxMDAgbU0iKSkKICApCmRhdC5mNnMKYGBgCiMjIyBQbG90IChhbGwgZGF0YSkKYGBge3J9CmRhdC5mNnMgJT4lIAogICMgbGVhdmUgb3V0IHRoZSBsb3dlc3QgY29uY2VudHJhdGlvbiBpbiBlYWNoIGdyb3VwCiAgI2ZpbHRlcighSDJPMiAlaW4lIGMoIjIgbU0iLCAiNjAgbU0iKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IEgyTzIsIHkgPSByKSkgKyAjcC5zdXJ2aXZhbFstM10gKwogIGdlb21fcG9pbnQoYWVzKHNoYXBlID0gUHJpbWFyeSksIHN0cm9rZSA9IDEsIHNpemUgPSAyLCAKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC43KSkgKwogIHN0YXRfc3VtbWFyeShhZXMoZ3JvdXAgPSBQcmltYXJ5KSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjcpLAogICAgICAgICAgICAgICBmdW4gPSBtZWFuLCBmdW4ubWF4ID0gbWVhbiwgZnVuLm1pbiA9IG1lYW4sCiAgICAgICAgICAgICAgIGdlb20gPSAiY3Jvc3NiYXIiLCBjb2xvciA9ICJyZWQiLCB3aWR0aCA9IDAuNSkgKwogIGZhY2V0X3dyYXAofiBHZW5vdHlwZSwgbnJvdyA9IDIsIHNjYWxlcyA9ICJmcmVlX3giKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoIk1vY2siID0gMSwgIi1QaSIgPSAxNikpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50KSArCiAgeGxhYigiUHJpbWFyeSBzdHJlc3MgKDQ1IG1pbikiKSArIHlsYWIoIiUgc3Vydml2YWwiKSArCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTQsIGJhc2VfbGluZV9zaXplID0gMSkgKwogIHBhbmVsX2JvcmRlcihjb2xvciA9ICJibGFjayIsIHNpemUgPSAxKSArCiAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDEpLCBmYWNlID0gMyksCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuNiwgMC4yKSwKICAgICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkKYGBgCgojIyMgMTAwIG1NIHZzIDEwMCBtTSB2cyA4MCBtTQpGb3IgdGhpcyBzZXQsIHRoZSBzYW1lIGNvbmNlbnRyYXRpb25zIG9mIEgyTzIgcmVzdWx0cyBpbiB2ZXJ5IHNpbWlsYXIgYmFzYWwgc3Vydml2YWwgcmF0ZXMuIEhlcmUsIHdlIHdpbGwgdGVzdCA2MCBtTSBmb3IgYWxsIHRocmVlLgpgYGB7cn0KZGF0LmY2czEgPC0gZGF0LmY2cyAlPiUgCiAgbXV0YXRlKEdyb3VwID0gcGFzdGUoR2Vub3R5cGUsIEgyTzIsIHNlcCA9ICJfIikpICU+JSAKICBmaWx0ZXIoR3JvdXAgJWluJSBjKCJ3aWxkdHlwZV8xMDAgbU0iLCAicmltMTXOlF84MCBtTSIsICJyaW0xNTo6UklNMTVfMTAwIG1NIikpCiN3cml0ZV90c3YoZGF0LmYzYSwgZmlsZSA9ICIuLi9pbnB1dC8yMDIzMDUyMC1maWctM2QtZGF0YS1oYi50c3YiKQpgYGAKCiMjIyMgUGxvdApgYGB7cn0KcCA8LSBkYXQuZjZzMSAlPiUgCiAgbXV0YXRlKEdlbm90eXBlID0gZmN0X3JlY29kZShHZW5vdHlwZSwgIldUIiA9ICJ3aWxkdHlwZSIpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gUHJpbWFyeSwgeSA9IHIpKSArCiAgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBQcmltYXJ5KSwgc3Ryb2tlID0gMSwgc2l6ZSA9IDIsCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcigwLjEpKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKG5hbWUgPSAiIiwgdmFsdWVzID0gYygxLCAxNiksIGd1aWRlID0gIm5vbmUiKSArCiAgI3NjYWxlX2ZpbGxfbWFudWFsKG5hbWUgPSBicXVvdGUoSFsyXSpPWzJdKSwgdmFsdWVzID0gYygid2hpdGUiLCAiZ3JheTgwIikpICsKICBwLnN1cnZpdmFsWy0xXSArCiAgZmFjZXRfd3JhcCh+R2Vub3R5cGUgKyBIMk8yLCBucm93ID0gMSkgKwogIHBhbmVsX2JvcmRlcihjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpICsKICB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpCiAgICAgICAgKQpwCgojZ2dzYXZlKCIuLi9vdXRwdXQvMjAyMzA4MTgtZmlnNnN1cC1hc3ItcmltMTUtY29tcC0xLnBuZyIsIHdpZHRoID0gNSwgaGVpZ2h0ID0gMykKYGBgCgoKIyMjIyBTdGF0aXN0aWNhbCB0ZXN0CjEuIERldGVybWluZSBpZiB0aGUgYmFzYWwgc3Vydml2YWwgcmF0ZXMgYXJlIGRpZmZlcmVudCBiZXR3ZWVuIGdlbm90eXBlcyAoV2lsY294b24gc2lnbmVkLXJhbmsgdGVzdCkKMS4gRGV0ZXJtaW5lIGlmIHRoZSBwcmltYXJ5IHN0cmVzcyBlbmhhbmNlZCB0aGUgc3Vydml2YWwgaW4gX2VhY2hfIGdlbm90eXBlIChXaWxjb3hvbiBzaWduZWQtcmFuayB0ZXN0KQoKXyoqQmFzYWwgc3Vydml2YWwgcmF0ZSoqXwoKQmVjYXVzZSB3ZSBoYXZlIHRocmVlIGdyb3VwcyBoZXJlLCBteSBzdHJhdGVneSBpcyB0byBmaXJzdCBwZXJmb3JtIGFuIEFOT1ZBLWxpa2UsIGJ1dCByYW5rLWJhc2VkLCBLcnVzYWwtV2FsbGlzIHRlc3QsIHdoZXJlIHRoZSBudWxsIGh5cG90aGVzaXMgaXMgdGhhdCBhbGwgdGhyZWUgZ3JvdXBzJyBkaXN0cmlidXRpb24gaGFzIHRoZSBzYW1lICJsb2NhdGlvbiIgKD1tZWFuKS4gSSBhbHNvIHBlcmZvcm1lZCBhIHBhaXJ3aXNlIFdpbGNveHNvbiByYW5rIHN1bSB0ZXN0LCBhbHRob3VnaCB0aGF0IGlzIG5vdCBuZWNlc3NhcnkgaWYgdGhlIGZpcnN0IHRlc3QgaXMgZGVlbWVkIGluc2lnbmlmaWNhbnQuCmBgYHtyfQp0bXAgPC0gZGF0LmY2czEgJT4lIAogIGZpbHRlcihQcmltYXJ5ID09ICJNb2NrIikgJT4lIAogIHNlbGVjdChEYXRlLCBHZW5vdHlwZSwgcikgJT4lIAogIG11dGF0ZShyID0gYXMuZG91YmxlKHIpKSAlPiUgCiAgYXJyYW5nZShHZW5vdHlwZSkKCnRtcCAlPiUgZ3JvdXBfYnkoR2Vub3R5cGUpICU+JSBzdW1tYXJpemUobWVhbiA9IG1lYW4ociksIHNkID0gbnVtKHNkKHIpLCBkaWdpdHMgPSAzKSkKCmtydXNrYWwudGVzdChyIH4gR2Vub3R5cGUsIGRhdGEgPSB0bXApCnBhaXJ3aXNlLndpbGNveC50ZXN0KHggPSB0bXAkciwgZyA9IHRtcCRHZW5vdHlwZSkKYGBgCgo+IGJhc2FsIHN1cnZpdmFsIHJhdGVzIG5vdCBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBiZXR3ZWVuIGdlbm90eXBlcyBhdCB0aGUgY2hvc2VuIFtIMk8yXSwgYXMgc2hvd24gYnkgYm90aCB0aGUgKEFOT1ZBLWVxdWl2YWxlbnQsIHJhbmstYmFzZWQpIEtydXNrYWwtV2FsbGlzIHRlc3QgYW5kIHRoZSAodC10ZXN0IGVxdWl2YWxlbnQpIHBhaXJ3aXNlIFdpbGNveHNvbiByYW5rLXN1bSB0ZXN0ICh1bnBhaXJlZCkuIFAtdmFsdWVzIGZyb20gdGhlIGxhdHRlciB3ZXJlIGFkanVzdGVkIGZvciBtdWx0aXBsZSBjb21wYXJpc29uIHVzaW5nIEhvbG0ncyBtZXRob2QgKHVuaWZvcm1seSBtb3JlIHBvd2VyZnVsIHRoYW4gQm9uZmVycm9uaSkKCl8qKlN1cnZpdmFsIHJhdGUgd2l0aCB0aGUgcHJpbWFyeSBzdHJlc3MqKl8KClNhbWUgc3RyYXRlZ3kgYXMgYWJvdmUKYGBge3J9CnRtcCA8LSBkYXQuZjZzMSAlPiUgCiAgZmlsdGVyKFByaW1hcnkgPT0gIi1QaSIpICU+JSAKICBzZWxlY3QoRGF0ZSwgR2Vub3R5cGUsIHIpICU+JSAKICBhcnJhbmdlKEdlbm90eXBlKQoKdG1wICU+JSBncm91cF9ieShHZW5vdHlwZSkgJT4lIHN1bW1hcml6ZShtZWFuID0gbWVhbihyKSwgc2QgPSBudW0oc2QociksIGRpZ2l0cyA9IDMpKQoKa3J1c2thbC50ZXN0KGFzLmRvdWJsZShyKSB+IEdlbm90eXBlLCBkYXRhID0gdG1wKQpwYWlyd2lzZS53aWxjb3gudGVzdCh4ID0gdG1wJHIsIGcgPSB0bXAkR2Vub3R5cGUsIHBhaXJlZCA9IEZBTFNFKQpgYGAKPiBzdXJ2aXZhbCByYXRlcyB3aXRoIHByaW1hcnkgc3RyZXNzIGFyZSBsb3dlciBpbiByaW0xNeKIhiB0aGFuIGVpdGhlciB0aGUgd2lsZHR5cGUgb3IgdGhlIGNvbXBsZW1lbnQsIGJ1dCB0aGUgZGlmZmVyZW5jZSBpcyBub3Qgc2lnbmlmaWNhbnQKCl8qKlByaW1hcnkgc3RyZXNzIGVuaGFuY2VkIGluIHdpbGR0eXBlKipfCgpIZXJlLCBJIGZpcnN0IGNhbGN1bGF0ZSB0aGUgQVNSIHNjb3JlIGFuZCBpdHMgc3VtbWFyeSBzdGF0aXN0aWNzLiBUbyBkZXRlcm1pbmUgaWYgdGhlIGVmZmVjdCBpcyBzaWduaWZpY2FudCwgSSBwZXJmb3JtIHRocmVlIHR5cGVzIG9mIHRlc3RzOgotIFQtdGVzdCwgbW9zdCBwb3dlcmZ1bCBidXQgcmVxdWlyaW5nIHRoZSBkYXRhIHRvIGJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLCB3aGljaCBvdXJzIGRvZXNuJ3QuCi0gV2lsY294c29uIHNpZ25lZC1yYW5rIHRlc3QsIHBhaXJlZAotIFdpbGNveHNvbiByYW5rLXN1bSB0ZXN0ICg9TWFubi1XaGl0bmV5J3MgVSB0ZXN0KSwgdW5wYWlyZWQKCkluIHRoZSBwYXBlciwgd2UgcmVwb3J0IHRoZSBQLXZhbHVlcyBvZiB0aGUgV2lsY294c29uIHNpZ25lZC1yYW5rIHRlc3QKCkNvbXBhcmlzb24gYmV0d2VlbiByIGFuZCByJywgcGFpcmVkLCBzaWduZWQtcmFuayB0ZXN0LgpgYGB7cn0KdG1wIDwtIGRhdC5mNnMxICU+JSAKICBmaWx0ZXIoR2Vub3R5cGUgPT0gIndpbGR0eXBlIikgJT4lIAogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKERhdGUsIFN0cmFpbiksIG5hbWVzX2Zyb20gPSBQcmltYXJ5LCB2YWx1ZXNfZnJvbSA9IHIpICU+JSAKICBtdXRhdGUoQVNSID0gYC1QaWAvTW9jaykKCnRtcAoKeCA8LSBIbWlzYzo6c21lYW4uY2wuYm9vdCh0bXAkQVNSKQpzcHJpbnRmKCJBU1Jfc2NvcmUgbWVhbiA9ICUuMmYsIDk1JSUgQ0kgYnkgYm9vdHN0cmFwID0gWyUuMmYsICUuMmZdIiwgeFsxXSwgeFsyXSwgeFszXSkKCndpdGgodG1wLCB0LnRlc3QoYXMubnVtZXJpYyhgLVBpYCksIGFzLm51bWVyaWMoTW9jayksIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKd2l0aCh0bXAsIHdpbGNveC50ZXN0KGAtUGlgLCBNb2NrLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpCmBgYAoKX1ByaW1hcnkgc3RyZXNzIGVuaGFuY2VkIGluIFJJTTE1IGNvbXBsZW1lbnRfCgpDb21wYXJpc29uIGJldHdlZW4gciBhbmQgcicsIHBhaXJlZCwgc2lnbmVkLXJhbmsgdGVzdC4KYGBge3J9CnRtcCA8LSBkYXQuZjZzMSAlPiUgCiAgZmlsdGVyKEdlbm90eXBlID09ICJyaW0xNTo6UklNMTUiKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoRGF0ZSwgU3RyYWluKSwgbmFtZXNfZnJvbSA9IFByaW1hcnksIHZhbHVlc19mcm9tID0gcikgJT4lIAogIG11dGF0ZShBU1IgPSBgLVBpYC9Nb2NrKQoKdG1wCgp4IDwtIEhtaXNjOjpzbWVhbi5jbC5ib290KHRtcCRBU1IpCnNwcmludGYoIkFTUl9zY29yZSBtZWFuID0gJS4yZiwgOTUlJSBDSSBieSBib290c3RyYXAgPSBbJS4yZiwgJS4yZl0iLCB4WzFdLCB4WzJdLCB4WzNdKQoKd2l0aCh0bXAsIHQudGVzdChhcy5udW1lcmljKGAtUGlgKSwgYXMubnVtZXJpYyhNb2NrKSwgcGFpcmVkID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAiZyIpKQp3aXRoKHRtcCwgd2lsY294LnRlc3QoYC1QaWAsIE1vY2ssIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKYGBgCgpfKipQcmltYXJ5IHN0cmVzcyBlZmZlY3QgaW4gcmltMTXOlCoqXwoKUGFpcmVkLCBzaWduZWQtcmFuayB0ZXN0CmBgYHtyfQp0bXAgPC0gZGF0LmY2czEgJT4lIAogIGZpbHRlcihHZW5vdHlwZSA9PSAicmltMTXOlCIpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhEYXRlLCBTdHJhaW4pLCBuYW1lc19mcm9tID0gUHJpbWFyeSwgdmFsdWVzX2Zyb20gPSByKSAlPiUgCiAgbXV0YXRlKEFTUiA9IGAtUGlgL01vY2spCgp0bXAKCnggPC0gSG1pc2M6OnNtZWFuLmNsLmJvb3QodG1wJEFTUikKc3ByaW50ZigiQVNSX3Njb3JlIG1lYW4gPSAlLjJmLCA5NSUlIENJIGJ5IGJvb3RzdHJhcCA9IFslLjJmLCAlLjJmXSIsIHhbMV0sIHhbMl0sIHhbM10pCgp3aXRoKHRtcCwgdC50ZXN0KGFzLm51bWVyaWMoYC1QaWApLCBhcy5udW1lcmljKE1vY2spLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpCndpdGgodG1wLCB3aWxjb3gudGVzdChgLVBpYCwgTW9jaywgcGFpcmVkID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAiZyIpKQpgYGAKCj4gQXQgdGhpcyBzZXQgb2YgY29uY2VudHJhdGlvbnMsIGFsbCB0aHJlZSBzdHJhaW5zIHNob3dlZCBzaWduaWZpY2FudCBBU1IgZWZmZWN0cy4KCl8qKkNvbXBhcmluZyB0aGUgQVNSIGVmZmVjdCBpbiByaW0xNc6ULHJpbTE1OjpSSU0xNSBhbmQgd2lsZCB0eXBlKipfCgpVbnBhaXJlZCwgcmFuay1zdW0gdGVzdApgYGB7cn0KdG1wIDwtIGRhdC5mNnMxICU+JSAKICAjZmlsdGVyKEdlbm90eXBlID09ICJjdGExzpQiKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoRGF0ZSwgU3RyYWluLCBHZW5vdHlwZSksIG5hbWVzX2Zyb20gPSBQcmltYXJ5LCB2YWx1ZXNfZnJvbSA9IHIpICU+JSAKICBtdXRhdGUoQVNSID0gYC1QaWAvTW9jaykgJT4lIAogIGFycmFuZ2UoR2Vub3R5cGUpCgp0bXAgJT4lIGdyb3VwX2J5KEdlbm90eXBlKSAlPiUgCiAgc3VtbWFyaXplKEFTUl9zY29yZSA9IHBhc3RlKHJvdW5kKGFzLm51bWVyaWMoQVNSKSwxKSwgY29sbGFwc2UgPSAiLCAiKSwgCiAgICAgICAgICAgIG1lYW4gPSBtZWFuKEFTUiksIHNkID0gc2QoQVNSKSkKCmtydXNrYWwudGVzdChhcy5udW1lcmljKEFTUikgfiBHZW5vdHlwZSwgZGF0YSA9IHRtcCkKcGFpcndpc2Uud2lsY294LnRlc3QoeCA9IGFzLm51bWVyaWModG1wJEFTUiksIGcgPSB0bXAkR2Vub3R5cGUsIHBhaXJlZCA9IEZBTFNFLCBwLmFkanVzdC5tZXRob2QgPSAiaG9sbSIpCmBgYAogCj4gVGhlIHRlc3RzIG9mIGludGVyZXN0cyBhbW9uZyB0aGUgcGFpcndpc2UgY29tcGFyaXNvbnMgYXJlIGJldHdlZW4gdGhlIHdpbGQgdHlwZSBhbmQgdGhlIG90aGVyIHR3byBzdHJhaW5zCj4gQXBwbHlpbmcgQm9uZmVycm9uaSBjb3JyZWN0aW9uIHRvIHRoZSB0d28gdGVzdHMsIHdlIGNvbmNsdWRlIHRoYXQgX3JpbTE14oiGXyBpcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIHRoZSB3aWxkIHR5cGUgaW4gaXRzIEFTUiBlZmZlY3QgKFAgPSAwLjAzNCksIHdoaWxlIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gX2N0YTE6OkNUQTFfIGFuZCB3aWxkIHR5cGUgaXMgbm90IChQID0gMC40OCkuCgojIyMgODAgbU0gdnMgODAgbU0gdnMgNjAgbU0KQSBzZWNvbmQgc2V0IG9mIGNvbmNlbnRyYXRpb25zCmBgYHtyfQpkYXQuZjZzMiA8LSBkYXQuZjZzICU+JSAKICBtdXRhdGUoR3JvdXAgPSBwYXN0ZShHZW5vdHlwZSwgSDJPMiwgc2VwID0gIl8iKSkgJT4lIAogIGZpbHRlcihHcm91cCAlaW4lIGMoIndpbGR0eXBlXzgwIG1NIiwgInJpbTE1zpRfNjAgbU0iLCAicmltMTU6OlJJTTE1XzgwIG1NIikpCiN3cml0ZV90c3YoZGF0LmYzYSwgZmlsZSA9ICIuLi9pbnB1dC8yMDIzMDUyMC1maWctM2QtZGF0YS1oYi50c3YiKQpgYGAKCiMjIyMgUGxvdApgYGB7cn0KcCA8LSBkYXQuZjZzMiAlPiUgCiAgbXV0YXRlKEdlbm90eXBlID0gZmN0X3JlY29kZShHZW5vdHlwZSwgIldUIiA9ICJ3aWxkdHlwZSIpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gUHJpbWFyeSwgeSA9IHIpKSArCiAgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBQcmltYXJ5KSwgc3Ryb2tlID0gMSwgc2l6ZSA9IDIsCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcigwLjEpKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKG5hbWUgPSAiIiwgdmFsdWVzID0gYygxLCAxNiksIGd1aWRlID0gIm5vbmUiKSArCiAgI3NjYWxlX2ZpbGxfbWFudWFsKG5hbWUgPSBicXVvdGUoSFsyXSpPWzJdKSwgdmFsdWVzID0gYygid2hpdGUiLCAiZ3JheTgwIikpICsKICBwLnN1cnZpdmFsWy0xXSArCiAgZmFjZXRfd3JhcCh+R2Vub3R5cGUgKyBIMk8yLCBucm93ID0gMSkgKwogIHBhbmVsX2JvcmRlcihjb2xvciA9ICJibGFjayIsIHNpemUgPSAxLjUpICsKICB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpCiAgICAgICAgKQpwCgpnZ3NhdmUoIi4uL291dHB1dC8yMDIzMDgxOC1maWc2c3VwLWFzci1yaW0xNS1jb21wLTIucG5nIiwgd2lkdGggPSA1LCBoZWlnaHQgPSAzKQpgYGAKCl8qKlN0YXRpc3RpY2FsIHRlc3RzKipfCgojIyMjIFN0YXRpc3RpY2FsIHRlc3QKMS4gRGV0ZXJtaW5lIGlmIHRoZSBiYXNhbCBzdXJ2aXZhbCByYXRlcyBhcmUgZGlmZmVyZW50IGJldHdlZW4gZ2Vub3R5cGVzIChXaWxjb3hvbiBzaWduZWQtcmFuayB0ZXN0KQoxLiBEZXRlcm1pbmUgaWYgdGhlIHByaW1hcnkgc3RyZXNzIGVuaGFuY2VkIHRoZSBzdXJ2aXZhbCBpbiBfZWFjaF8gZ2Vub3R5cGUgKFdpbGNveG9uIHNpZ25lZC1yYW5rIHRlc3QpCgpfKipCYXNhbCBzdXJ2aXZhbCByYXRlKipfCgpCZXR3ZWVuIHd0IGFuZCBjdGEx4oiGLCB1bnBhaXJlZCwgcmFuay1zdW0gdGVzdC4KYGBge3J9CnRtcCA8LSBkYXQuZjZzMiAlPiUgCiAgZmlsdGVyKFByaW1hcnkgPT0gIk1vY2siKSAlPiUgCiAgc2VsZWN0KERhdGUsIEdlbm90eXBlLCByKSAlPiUgCiAgbXV0YXRlKHIgPSBhcy5kb3VibGUocikpICU+JSAKICBhcnJhbmdlKEdlbm90eXBlKQoKdG1wICU+JSBncm91cF9ieShHZW5vdHlwZSkgJT4lIHN1bW1hcml6ZShtZWFuID0gbWVhbihyKSwgc2QgPSBudW0oc2QociksIGRpZ2l0cyA9IDMpKQoKa3J1c2thbC50ZXN0KHIgfiBHZW5vdHlwZSwgZGF0YSA9IHRtcCkKcGFpcndpc2Uud2lsY294LnRlc3QoeCA9IHRtcCRyLCBnID0gdG1wJEdlbm90eXBlKQpgYGAKCj4gYmFzYWwgc3Vydml2YWwgcmF0ZXMgbm90IHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGJldHdlZW4gZ2Vub3R5cGVzIGF0IHRoZSBjaG9zZW4gW0gyTzJdCgpfKipTdXJ2aXZhbCByYXRlIHdpdGggdGhlIHByaW1hcnkgc3RyZXNzKipfCgpCZXR3ZWVuIGdlbm90eXBlcywgdW5wYWlyZWQsIHJhbmstc3VtIHRlc3QuCmBgYHtyfQp0bXAgPC0gZGF0LmY2czIgJT4lIAogIGZpbHRlcihQcmltYXJ5ID09ICItUGkiKSAlPiUgCiAgc2VsZWN0KERhdGUsIEdlbm90eXBlLCByKSAlPiUgCiAgYXJyYW5nZShHZW5vdHlwZSkKCnRtcCAlPiUgZ3JvdXBfYnkoR2Vub3R5cGUpICU+JSBzdW1tYXJpemUobWVhbiA9IG1lYW4ociksIHNkID0gbnVtKHNkKHIpLCBkaWdpdHMgPSAzKSkKCmtydXNrYWwudGVzdChhcy5kb3VibGUocikgfiBHZW5vdHlwZSwgZGF0YSA9IHRtcCkKcGFpcndpc2Uud2lsY294LnRlc3QoeCA9IHRtcCRyLCBnID0gdG1wJEdlbm90eXBlLCBwYWlyZWQgPSBGQUxTRSkKYGBgCj4gc3Vydml2YWwgcmF0ZXMgd2l0aCBwcmltYXJ5IHN0cmVzcyBpcyBsb3dlciBpbiByaW0xNeKIhiB0aGFuIGluIHRoZSB3aWxkIHR5cGUgb3IgdGhlIGNvbXBsZW1lbnQgc3RyYWluLiBUaGUgZGlmZmVyZW5jZSBpcyBhcHByb2FjaGluZyBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UgYXQgYSAwLjA1IGxldmVsIGJ5IEtydXNrYWwtV2FsbGlzIHJhbmsgc3VtIHRlc3QuCgpfKipQcmltYXJ5IHN0cmVzcyBlbmhhbmNlZCBpbiB3aWxkdHlwZSoqXwoKQ29tcGFyaXNvbiBiZXR3ZWVuIHIgYW5kIHInLCBwYWlyZWQsIHNpZ25lZC1yYW5rIHRlc3QuCmBgYHtyfQp0bXAgPC0gZGF0LmY2czIgJT4lIAogIGZpbHRlcihHZW5vdHlwZSA9PSAid2lsZHR5cGUiKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoRGF0ZSwgU3RyYWluKSwgbmFtZXNfZnJvbSA9IFByaW1hcnksIHZhbHVlc19mcm9tID0gcikgJT4lIAogIG11dGF0ZShBU1IgPSBgLVBpYC9Nb2NrKQoKdG1wCgp4IDwtIEhtaXNjOjpzbWVhbi5jbC5ib290KHRtcCRBU1IpCnNwcmludGYoIkFTUl9zY29yZSBtZWFuID0gJS4yZiwgOTUlJSBDSSBieSBib290c3RyYXAgPSBbJS4yZiwgJS4yZl0iLCB4WzFdLCB4WzJdLCB4WzNdKQoKd2l0aCh0bXAsIHQudGVzdChhcy5udW1lcmljKGAtUGlgKSwgYXMubnVtZXJpYyhNb2NrKSwgcGFpcmVkID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAiZyIpKQp3aXRoKHRtcCwgd2lsY294LnRlc3QoYC1QaWAsIE1vY2ssIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKYGBgCgpfKipQcmltYXJ5IHN0cmVzcyBlbmhhbmNlZCBpbiBSSU0xNSBjb21wbGVtZW50KipfCgpDb21wYXJpc29uIGJldHdlZW4gciBhbmQgcicsIHBhaXJlZCwgc2lnbmVkLXJhbmsgdGVzdC4KYGBge3J9CnRtcCA8LSBkYXQuZjZzMiAlPiUgCiAgZmlsdGVyKEdlbm90eXBlID09ICJyaW0xNTo6UklNMTUiKSAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoRGF0ZSwgU3RyYWluKSwgbmFtZXNfZnJvbSA9IFByaW1hcnksIHZhbHVlc19mcm9tID0gcikgJT4lIAogIG11dGF0ZShBU1IgPSBgLVBpYC9Nb2NrKQoKdG1wCgp4IDwtIEhtaXNjOjpzbWVhbi5jbC5ib290KHRtcCRBU1IpCnNwcmludGYoIkFTUl9zY29yZSBtZWFuID0gJS4yZiwgOTUlJSBDSSBieSBib290c3RyYXAgPSBbJS4yZiwgJS4yZl0iLCB4WzFdLCB4WzJdLCB4WzNdKQoKd2l0aCh0bXAsIHQudGVzdChhcy5udW1lcmljKGAtUGlgKSwgYXMubnVtZXJpYyhNb2NrKSwgcGFpcmVkID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAiZyIpKQp3aXRoKHRtcCwgd2lsY294LnRlc3QoYC1QaWAsIE1vY2ssIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSkKYGBgCgpfKipQcmltYXJ5IHN0cmVzcyBlZmZlY3QgaW4gcmltMTXOlCoqXwoKUGFpcmVkLCBzaWduZWQtcmFuayB0ZXN0CmBgYHtyfQp0bXAgPC0gZGF0LmY2czIgJT4lIAogIGZpbHRlcihHZW5vdHlwZSA9PSAicmltMTXOlCIpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhEYXRlLCBTdHJhaW4pLCBuYW1lc19mcm9tID0gUHJpbWFyeSwgdmFsdWVzX2Zyb20gPSByKSAlPiUgCiAgbXV0YXRlKEFTUiA9IGAtUGlgL01vY2spCgp0bXAKCnggPC0gSG1pc2M6OnNtZWFuLmNsLmJvb3QodG1wJEFTUikKc3ByaW50ZigiQVNSX3Njb3JlIG1lYW4gPSAlLjJmLCA5NSUlIENJIGJ5IGJvb3RzdHJhcCA9IFslLjJmLCAlLjJmXSIsIHhbMV0sIHhbMl0sIHhbM10pCgp3aXRoKHRtcCwgdC50ZXN0KGFzLm51bWVyaWMoYC1QaWApLCBhcy5udW1lcmljKE1vY2spLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpCndpdGgodG1wLCB3aWxjb3gudGVzdChgLVBpYCwgTW9jaywgcGFpcmVkID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAiZyIpKQpgYGAKPiBBU1IgZWZmZWN0IG5vdCBzaWduaWZpY2FudCBpbiBjdGEx4oiGLgoKXyoqQ29tcGFyaW5nIHRoZSBBU1IgZWZmZWN0IGluIHJpbTE1zpQscmltMTU6OlJJTTE1IGFuZCB3aWxkIHR5cGUqKl8KClVucGFpcmVkLCByYW5rLXN1bSB0ZXN0CmBgYHtyfQp0bXAgPC0gZGF0LmY2czIgJT4lIAogICNmaWx0ZXIoR2Vub3R5cGUgPT0gImN0YTHOlCIpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhEYXRlLCBTdHJhaW4sIEdlbm90eXBlKSwgbmFtZXNfZnJvbSA9IFByaW1hcnksIHZhbHVlc19mcm9tID0gcikgJT4lIAogIG11dGF0ZShBU1IgPSBgLVBpYC9Nb2NrKSAlPiUgCiAgYXJyYW5nZShHZW5vdHlwZSkKCnRtcCAlPiUgZ3JvdXBfYnkoR2Vub3R5cGUpICU+JSAKICBzdW1tYXJpemUoQVNSX3Njb3JlID0gcGFzdGUocm91bmQoYXMubnVtZXJpYyhBU1IpLDEpLCBjb2xsYXBzZSA9ICIsICIpLCAKICAgICAgICAgICAgbWVhbiA9IG1lYW4oQVNSKSwgc2QgPSBzZChBU1IpKQoKa3J1c2thbC50ZXN0KGFzLm51bWVyaWMoQVNSKSB+IEdlbm90eXBlLCBkYXRhID0gdG1wKQpwYWlyd2lzZS53aWxjb3gudGVzdCh4ID0gYXMubnVtZXJpYyh0bXAkQVNSKSwgZyA9IHRtcCRHZW5vdHlwZSwgcGFpcmVkID0gRkFMU0UsIHAuYWRqdXN0Lm1ldGhvZCA9ICJub25lIikKYGBgCgojIyBGaWc3XzE6IEFTUiBpbiB3dCB3aXRoIHJhcGFteWNpbgpfKipHb2FsKipfCgpUZXN0IHRoZSBoeXBvdGhlc2lzIHRoYXQgZGlyZWN0IGluaGliaXRpb24gb2YgVE9SQzEgY2FuIHByb3ZpZGUgQVNSIGluIF9DLiBnbGFicmF0YV8uIFdlIHdpbGwgYWxzbyB0ZXN0IF9TLiBjZXJldmlzaWFlXyB0byBkZXRlcm1pbmUgaWYgdGhlIG5lZ2F0aXZlIHJlZ3VsYXRpb24gYnkgVE9SQzEgb24gc3RyZXNzIHJlc3BvbnNlIGdlbmVzIGJlaGluZCB0aGUgQVNSIGlzIGNvbnNlcnZlZC4KCl8qKlJhdGlvbmFsZSoqXwoKSWYgVE9SQzEgaW5oaWJpdGlvbiBieSBwaG9zcGhhdGUgbGltaXRhdGlvbiBkaXJlY3RseSBjb250cmlidXRlcyB0byB0aGUgQVNSLCB3ZSBzaG91bGQgYmUgYWJsZSB0byBtaW1pYyB0aGUgZWZmZWN0IGJ5IGFydGlmaWNpYWxseSBpbmhpYml0aW5nIFRPUkMxIHdpdGggdGhlIGRydWcgcmFwYW15Y2luLiBUaGUgcHJlZGljdGlvbiBpcyB0aGF0IHJhcGFteWNpbiB0cmVhdG1lbnQgc2hvdWxkIGluZHVjZSBDdGExLUdGUCBhbmQgcHJvdmlkZSBBU1IuCgpfKipEYXRhKipfCgpTcGVjaWVzICAgICAgIFJhcGFteWNpbiAobmcvbUwpICAgIEgyTzIgICAgICAgIERlc2NyaXB0aW9uIAotLS0tLS0tLSAgICAgIC0tLS0tLS0tLS0tLS0tLS0tLSAgIC0tLS0tLSAgICAgIC0tLS0tLS0tLS0tLQpDLiBnbGFicmF0YSAgIDUwLCA2Mi41LCAxMjUsIDE1MCAgIDYwIG1NICAgICAgIGZ1bGwgQVNSIGV4cGVyaW1lbnQKUy4gY2VyZXZpc2lhZSA1MCwgNjIuNSwgMTI1LCAxNTAgICA2ICBtTSAgICAgICBmdWxsIEFTUiBleHBlcmltZW50CgpEYXRlICAgICAgIFNwZWNpZXMgICBSYXBhIChuZy9tTCkgIEgyTzIgICAgICAgIFN0cmFpbiAKLS0tLS0gICAgICAtLS0tLS0tLSAgLS0tLS0tLS0tLS0tICAtLS0tICAgICAgICAtLS0tLS0tCjAxLzEyLzIzICAgQ2cgICAgICAgIDYyLjUsIDEyNSAgICAgNjAgbU0gICAgICAgeUgxODEKMDEvMTgvMjMgICBDZyAgICAgICAgNjIuNSwgMTI1ICAgICA2MCBtTSAgICAgICB5SDE4MQowMS8yMS8yMyAgIFNjICAgICAgICA2Mi41LCAxMjUgICAgIDQsIDYgbU0gICAgIHlIMTU0CjAxLzIxLzIzICAgQ2cgICAgICAgIDYyLjUsIDEyNSAgICAgNDAsIDYwIG1NICAgeUgxODEKMDEvMjUvMjMgICBTYyAgICAgICAgNjIuNSwgMTI1ICAgICA0LCA2IG1NICAgICB5SDE1NAowMS8yNS8yMyAgIENnICAgICAgICA2Mi41LCAxMjUgICAgIDQwLCA2MCBtTSAgIHlIMTgxCjAxLzI2LzIzICAgU2MgICAgICAgIDYyLjUsIDEyNSAgICAgNCwgNiBtTSAgICAgeUgxNTQKMDEvMjYvMjMgICBDZyAgICAgICAgNjIuNSwgMTI1ICAgICA0MCwgNjAgbU0gICB5SDE4MQowMS8zMS8yMyAgIFNjICAgICAgICA2Mi41LCAxMjUgICAgIDQsIDYgbU0gICAgIHlIMTU0CjAxLzMxLzIzICAgQ2cgICAgICAgIDYyLjUsIDEyNSAgICAgNDAsIDYwIG1NICAgeUgxODEKMDIvMDIvMjMgICBDZyAgICAgICAgNjIuNSwgMTI1ICAgICA0MCwgNjAgbU0gICB5SDE4MQoKXyoqTm90ZSoqXwoKSmlueWUgdXNlZCBsb3dlciBIMk8yIGNvbmNlbnRyYXRpb24gY29tcGFyZWQgd2l0aCBwcmVpdm91cyBBU1IgZXhwZXJpbWVudHMgKDEwMCBtTSBmb3IgQ2cgYW5kIDEwIG1NIGZvciBTYykgYmVjYXVzZSB0aGUgcHJpbWFyeSBzdHJlc3NlcyB0ZXN0ZWQgaGVyZSwgaS5lLiwgcmFwYW15Y2luIGFuZCBuaXRyb2dlbiBzdGFydmF0aW9uLCByZWR1Y2VkIHN1cnZpdmFsIHdoaWxlIHBob3NwaGF0ZSBzdGFydmF0aW9uIHVzZWQgaW4gcHJldmlvdXMgQVNSIGV4cGVyaW1lbnRzIGRpZG4ndC4gSW4gb3JkZXIgdG8gbWFpbnRhaW4gYSBzaW1pbGFyIENGVSBhdCB0aGUgZW5kLCBhIGxvd2VyIEgyTzIgY29uY2VudHJhdGlvbiB3YXMgYXBwbGllZC4KCmBgYHtyfQp0bXAgPC0gcmVhZF9jc3YoIi4uL2lucHV0LzIwMjMwMjA1LVNjLUNnLXJhcGFteWNpbi1uaXRyb2dlbi1BU1ItcmF3LmNzdiIsIGNvbF90eXBlcyA9IGNvbHMoKSwgY29tbWVudCA9ICIjIikgJT4lIAogIG11dGF0ZShEYXRlID0gZ3N1YigiZChcXGRcXGQpKFxcZFxcZCkoXFxkXFxkKSIsICJcXDEvXFwyL1xcMyIsIERhdGUpKQoKZGF0LmY3YSA8LSB0bXAgJT4lIAogIHJlbmFtZShQcmltYXJ5ID0gYDFzdF9TdHJlc3NgKSAlPiUgCiAgZ3JvdXBfYnkoRGF0ZSwgU3RyYWluLCBQcmltYXJ5KSAlPiUgCiAgbXV0YXRlKAogICAgc2NhbGVkID0gRGlsdXRpb25zICogQ291bnQgKiAxZS0yLAogICAgciA9IHNjYWxlZCAvIHNjYWxlZFtIMk8yID09ICJNb2NrIl0KICApICU+JSAKICAjIGNvbmZpcm1lZCB0aGF0IG15IGNhbGN1bGF0aW9uIChyKSBlcXVhbHMgSlkncyBNTy9NTSBhbmQgUE8vUE0KICAjIHByZXNlcnZlIGhlciBBU1JfU2NvcmUgY2FsY3VsYXRpb24gZm9yIG5vdwogIHNlbGVjdCgtYE1PL01NYCwgLWBQTy9QTWAsIC1BU1JfU2NvcmUsIEFTUl9TY29yZSkKCiMgZGF0YSBzYW5pdHkgY2hlY2ssIHF1aWNrIHZpZXcKc2FwcGx5KHNlbGVjdChkYXQuZjdhLCBTcGVjaWVzLCBTdHJhaW4sIEdlbm90eXBlKSwgdW5pcXVlKQpgYGAKCl8qKlBsb3R0aW5nKipfCgojIyMgRWZmZWN0IG9mIHByaW1hcnkgc3RyZXNzIChSYXBhbXljaW4gYW5kIC1OKSBvbiBzdXJ2aXZhbApKaW55ZSBtZW50aW9uZWQgdGhhdCB1bmxpa2UgcGhvc3BoYXRlIHN0YXJ2YXRpb24sIHJhcGFteWNpbiBhbmQgbml0cm9nZW4gc3RhcnZhdGlvbiByZWR1Y2Ugc3Vydml2YWwgYnkgdGhlbXNlbHZlcy4gVG8gc2VlIHRoaXMgbXlzZWxmLCBJJ20gcGxvdHRpbmcgdGhlIENGVSBhZnRlciBqdXN0IHRoZSBwcmltYXJ5IAoKYGBge3J9CnRtcCA8LSBkYXQuZjdhICU+JSAKICBmaWx0ZXIoSDJPMiA9PSAiTW9jayIpICU+JSAKICBncm91cF9ieShEYXRlLCBTcGVjaWVzKSAlPiUgCiAgbXV0YXRlKAogICAgIyBhcmJpdHJhcmlseSBkZWNpZGUgYW55IENGVSBjb3VudHMgPCAzIGFyZSBub3QgaW5jbHVkZWQgZHVlIHRvIGhpZ2ggQ1YKICAgIENvdW50ID0gaWZlbHNlKENvdW50IDwgMywgTkEsIENvdW50KSwKICAgIHNjYWxlZCA9IENvdW50ICogRGlsdXRpb25zICogMWUtMiwKICAgIHIgPSBzY2FsZWQgLyBzY2FsZWRbUHJpbWFyeSA9PSAiTW9jayJdCiAgKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBmaWx0ZXIoUHJpbWFyeSAhPSAiTW9jayIpICU+JSAKICBzZWxlY3QoRGF0ZSwgU3BlY2llcywgU3RyYWluLCBQcmltYXJ5LCBDb3VudCwgcikKCmRhdC5wcmltIDwtICByYXcgJT4lCiAgc2VwYXJhdGUoR3JvdXAsIGludG8gPSBjKCJQcmltYXJ5IiwgIlNlY29uZGFyeSIpLCBzZXAgPSAxKSAlPiUgCiAgIyB1c2UgdGhlIFMyIGRhdGFzZXQgdG8gZXhhbWluZSB0aGUgZWZmZWN0IG9mIHBob3NwaGF0ZSBzdGFydmF0aW9uIG9uIHN1cnZpdmFsCiAgZmlsdGVyKERhdGUgJWluJSB1c2UuczFiLCBTZWNvbmRhcnkgPT0gIk0iKSAlPiUgCiAgbXV0YXRlKAogICAgIyBhcmJpdHJhcmlseSBkZWNpZGUgYW55IENGVSBjb3VudHMgPCAzIGFyZSBub3QgaW5jbHVkZWQgZHVlIHRvIGhpZ2ggQ1YKICAgIENvdW50ID0gaWZlbHNlKENvdW50IDwgMywgTkEsIENvdW50KSwKICAgIHNjYWxlZCA9IENvdW50ICogRGlsdXRpb25zICogMWUtMgogICkgJT4lIAogIGdyb3VwX2J5KERhdGUsIFN0cmFpbikgJT4lIAogICMgY2FsY3VsYXRlIHIgYW5kIHInCiAgbXV0YXRlKHIgPSBzY2FsZWQgLyBzY2FsZWRbUHJpbWFyeSA9PSAiTSJdKSAlPiUgCiAgdW5ncm91cCgpICU+JSBmaWx0ZXIoUHJpbWFyeSAhPSAiTSIpICU+JSAKICBzZWxlY3QoRGF0ZSwgU3BlY2llcywgU3RyYWluLCBQcmltYXJ5LCBDb3VudCwgcikgJT4lIAogIGJpbmRfcm93cyh0bXApICU+JSAKICBtdXRhdGUoUHJpbWFyeSA9IGZhY3RvcihQcmltYXJ5LAogICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIlAiLCAiNjIuNSIsICIxMjUiLCAiME5pIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiLVBpIiwgIlJhcGFcbjYyLjUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSYXBhXG4xMjUiLCAiLU5pdHJvZ2VuIikpKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoZGF0LnByaW0sIGFlcyh4ID0gUHJpbWFyeSwgeSA9IHIpKSArIHAuYXNyICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAuMiwgMS4yLCBieSA9IDAuMiksIGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkgKwogIHhsYWIoIlByaW1hcnkgc3RyZXNzICg0NSBtaW4pIikgKyB5bGFiKCJTdXJ2aXZhbCAlIikKI2dnc2F2ZSgiLi4vb3V0cHV0LzIwMjMwMjExLXByaW1hcnktc3RyZXNzLWVmZmVjdC1vbi1zdXJ2aXZhbC5wbmciKQpgYGAKCl8qKlN0YXRpc3RpY2FsIHRlc3RzKipfCgpVc2UgdGhlIFtuZXN0LW1hcC11bm5lc3Qgd29ya2Zsb3ddKGh0dHBzOi8vYnJvb20udGlkeW1vZGVscy5vcmcvYXJ0aWNsZXMvYnJvb21fYW5kX2RwbHlyLmh0bWwpCgpgYGB7cn0KZGF0LnByaW0gJT4lIAogIHNlbGVjdChTcGVjaWVzLCBQcmltYXJ5LCByKSAlPiUgCiAgbmVzdChkYXRhID0gcikgJT4lIAogIG11dGF0ZSgKICAgIHRlc3QgPSBtYXAoZGF0YSwgfiB0LnRlc3QoLngsIG11ID0gMSwgYWx0ZXJuYXRpdmUgPSAidHdvIikpLAogICAgdGlkaWVkID0gbWFwKHRlc3QsIHRpZHkpCiAgKSAlPiUgCiAgdW5uZXN0KHRpZGllZCkgJT4lIAogIHNlbGVjdChTcGVjaWVzLCBQcmltYXJ5LCBtZWFuX3IgPSBlc3RpbWF0ZSwgcC52YWx1ZSwgY29uZi5sb3csIGNvbmYuaGlnaCwgYWx0ZXJuYXRpdmUpICU+JSAKICBtdXRhdGUoUC5hZGogPSBwLmFkanVzdChwLnZhbHVlLCBtZXRob2QgPSAiQkgiKSwKICAgICAgICAgYWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLCByb3VuZCwgZGlnaXRzID0gMykpICU+JSAKICBhcnJhbmdlKFNwZWNpZXMsIFByaW1hcnkpCmBgYAoKIyMjIENhbGlicmF0ZSBzZWNvbmRhcnkgc3RyZXNzIHN0cmVuZ3RoCkppbnllIHVzZWQgdHdvIHNldHMgb2YgSDJPMiBjb25jZW50cmF0aW9ucyBpbiB0aGlzIGV4cGVyaW1lbnQsIGkuZS4sIDQwLzQgbU0gYW5kIDYwLzYgbU0gZm9yIF9DLiBnbGFicmF0YV8gYW5kIF9TLiBjZXJldmlzaWFlXywgcmVzcGVjdGl2ZWx5LiAKCmBgYHtyfQp3aXRoKGRhdC5mN2EsIHRhYmxlKERhdGUsIHBhc3RlKFNwZWNpZXMsIEgyTzIsIHNlcCA9ICI6IikpKQpgYGAKCkZpcnN0LCB3ZSB3aWxsIHRlc3QgaWYgdGhlIHN1cnZpdmFsIHVuZGVyIHRoZXNlIEgyTzIgY29uY2VudHJhdGlvbnMgYXJlIGNvbXBhcmFibGUgYWNyb3NzIHNwZWNpZXMsIGJ5IGFuYWx5emluZyB0aGUgYmFzYWwgc3Vydml2YWwgcmF0ZSByCgpTdGF0aXN0aWNhbCB0ZXN0IGZvciBkaWZmZXJlbmNlcyBpbiBiYXNhbCBzdXJ2aXZhbCBiZXR3ZWVuIHNwZWNpZXMgYXQgNjAgb3IgNiBtTS4gQSBXaWxjb3hvbiBzaWduZWQtcmFuayB0ZXN0IGlzIHVzZWQgaGVyZSBzaW5jZSB0aGUgdHdvIGdyb3VwcyBhcmUgZGVwZW5kZW50ICg9Z3JvdXBlZCkgYnkgdGhlIGRheSBvZiB0aGUgZXhwZXJpbWVudC4gT25lIHJlcGxpY2F0ZSB3YXMgcnVuIHBlciBkYXkuIFVzaW5nIGEgcGFpcmVkLXRlc3QgZW5zdXJlcyB0aGF0IGRheS10by1kYXkgdmFyaWF0aW9uIGlzIGFjY291bnRlZCBmb3IuCmBgYHtyfQp0bXAgPC0gZGF0LmY3YSAlPiUgCiAgZmlsdGVyKEgyTzIgJWluJSBjKCI2MG1NIiwgIjZtTSIpLCBHcm91cCA9PSAiTU8iLCAKICAgICAgICAgIShEYXRlICVpbiUgYygiMDEvMTIvMjMiLCAiMDEvMTgvMjMiLCAiMDIvMDIvMjMiKSkpIyAlPiUgCnRtcCAlPiUgZ3JvdXBfYnkoU3BlY2llcykgJT4lIHN1bW1hcml6ZShtZWFuID0gbWVhbihyKSkKd2lsY294LnRlc3QociB+IFNwZWNpZXMsIGRhdGEgPSB0bXAsIHBhaXJlZCA9IFRSVUUpCmBgYAoKU3RhdGlzdGljYWwgdGVzdCBmb3IgZGlmZmVyZW5jZXMgaW4gYmFzYWwgc3Vydml2YWwgYmV0d2VlbiBzcGVjaWVzIGF0IDQwIG9yIDQgbU0uCmBgYHtyfQp0bXAgPC0gZGF0LmY3YSAlPiUgCiAgZmlsdGVyKEgyTzIgJWluJSBjKCI0MG1NIiwgIjRtTSIpLCBHcm91cCA9PSAiTU8iLCAhKERhdGUgJWluJSBjKCIwMi8wMi8yMyIpKSkKdG1wICU+JSBncm91cF9ieShTcGVjaWVzKSAlPiUgc3VtbWFyaXplKG1lYW4gPSBtZWFuKHIpKQp3aWxjb3gudGVzdChyIH4gU3BlY2llcywgZGF0YSA9IHRtcCwgcGFpcmVkID0gVFJVRSkKYGBgCj4geWVzLCB0aGUgc3Vydml2YWwgcmF0ZXMgYXJlIGNvbXBhcmFibGUgYmV0d2VlbiBzcGVjaWVzIGF0IHRoZSB0d28gcGFpcnMgb2YgY2hvc2VuIFtIMk8yXQoKU3RhdGlzdGljYWwgdGVzdCBmb3IgZGlmZmVyZW5jZXMgaW4gYmFzYWwgc3Vydml2YWwgYmV0d2VlbiB0aGUgaGlnaCBhbmQgbG93IEgyTzIgY29uY2VudHJhdGlvbnMgKDYwLzYgdnMgNDAvNCBtTSksIHNwZWNpZXMgY29tYmluZWQuCmBgYHtyfQp0bXAgPC0gZmlsdGVyKGRhdC5mN2EsIEdyb3VwID09ICJNTyIpICU+JSAKICBtdXRhdGUoc2Vjb25kYXJ5ID0gZmFjdG9yKEgyTzIsIGxldmVscyA9IGMoIjYwbU0iLCAiNm1NIiwgIjQwbU0iLCAiNG1NIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJoaWdoIiwgImhpZ2giLCAibG93IiwgImxvdyIpKSkKdG1wICU+JSAKICBncm91cF9ieShzZWNvbmRhcnksIFNwZWNpZXMpICU+JSAKICBzdW1tYXJpemUobWVhbiA9IG51bShtZWFuKHIpLCBkaWdpdHMgPSAzKSwgLmdyb3VwcyA9ICJkcm9wIikKd2lsY294LnRlc3QociB+IHNlY29uZGFyeSwgZGF0YSA9IHRtcCwgcGFpcmVkID0gRkFMU0UpCmFub3ZhKGxtKHIgfiBTcGVjaWVzICsgc2Vjb25kYXJ5LCBkYXRhID0gdG1wKSkKYGBgCgo+IFdlIGNhbiBjb25jbHVkZSB0aGF0IHRoZXJlIGlzIG5vIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgaW4gc3Vydml2YWwgd2hlbiBjb21wYXJpbmcgNDAgbU0gdnMgNCBtTSBmb3IgX0MuIGdsYWJyYXRhXyB2cyBfUy4gY2VyZXZpc2lhZV8uIFNpbWlsYXJseSwgdGhlcmUgaXMgbm8gc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBpbiBzdXJ2aXZhbCB3aGVuIDYwIG1NIGFuZCA2IG1NIHdlcmUgdXNlZCB0byB0cmVhdCB0aGUgdHdvIHNwZWNpZXMsIHJlc3BlY3RpdmVseS4KPiBIb3dldmVyLCB0aGUgc3Vydml2YWwgcmF0ZSBpcyBzaWduaWZpY2FudGx5IGxvd2VyIHVuZGVyIHRoZSBoaWdoZXIgc2V0IG9mIGNvbmNlbnRyYXRpb25zICg2MCBhbmQgNiBtTSkgY29tcGFyZWQgd2l0aCB0aGUgbG93ZXIgb25lcyAoNDAgYW5kIDQgbU0pCgojIyMgUmFwYW15Y2luIEFTUgpXZSB3aWxsIGZvY3VzIG9uIDYwLzYgbU0gZGF0YSBmb3IgcGxvdHRpbmcgYW5kIHN0YXRpc3RpY2FsIGFuYWx5c2VzLgpgYGB7cn0KIyB3ZSB3aWxsIG5vdCB1c2UgdGhlIGRheXMgb2YgZXhwZXJpbWVudHMgd2hlcmUgb25seSBvbmUgc3BlY2llcyB3YXMgYXNzYXllZApkYXQuN2FwIDwtIGRhdC5mN2EgJT4lIAogIG11dGF0ZSgKICAgIFNlY29uZGFyeSA9ICBmYWN0b3IoSDJPMiwgbGV2ZWxzID0gYygiNDBtTSIsICI0bU0iLCAiNjBtTSIsICI2bU0iKSwKICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiNDAvNG1NIiwgIjQwLzRtTSIsICI2MC82bU0iLCAiNjAvNm1NIikpCiAgKSAlPiUgCiAgZmlsdGVyKEgyTzIgIT0gIk1vY2siLCBQcmltYXJ5ICVpbiUgYygiMTI1IiwgIk1vY2siKSkgJT4lIAogIG11dGF0ZShQcmltYXJ5ID0gZmFjdG9yKFByaW1hcnksIGxldmVscyA9IGMoIk1vY2siLCAiMTI1IikpKQpgYGAKCm15IGNhbGN1bGF0aW9uIGlzIHRoZSBzYW1lIGFzIEpZJ3MKYGBgCndpdGgoZGF0LjdhcCwgc3VtKHJvdW5kKHJQL3IsIDUpICE9IHJvdW5kKEFTUl9TY29yZSwgNSkpKQpgYGAKCiMjIyMgUGxvdApgYGB7cn0KZGF0LjdhcCAlPiUgZmlsdGVyKFNlY29uZGFyeSA9PSAiNjAvNm1NIikgJT4lIAogIG11dGF0ZShQcmltYXJ5ID0gcmVjb2RlKFByaW1hcnksICIxMjUiID0gIjEyNSBuZy9tTCIpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gUHJpbWFyeSwgeSA9IHIpKSArIHAuc3Vydml2YWxbLTFdICsKICBnZW9tX2xpbmUoYWVzKGdyb3VwID0gcGFzdGUwKERhdGUsIFNlY29uZGFyeSkpLCBsaW5ldHlwZSA9IDIsIGxpbmV3aWR0aCA9IDAuMykgKyAKICBnZW9tX3BvaW50KHNoYXBlID0gMSwgc3Ryb2tlID0gMSwgc2l6ZSA9IDEpICsKICAjbGFicyh5ID0gIiUgc3Vydml2YWwiKSArIAogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkKI2dnc2F2ZSgiLi4vb3V0cHV0LzIwMjMwNTIwLXJhcGFteWNpbi1BU1IucG5nIiwgd2lkdGggPSA0LjUsIGhlaWdodCA9IDIuMikKYGBgCiAgCiMjIyMgU3RhdGlzdGljYWwgdGVzdAoKU3VtbWFyeSBzdGF0aXN0aWNzCmBgYHtyfQpkYXQuN2FzIDwtIGRhdC43YXAgJT4lIAogIGdyb3VwX2J5KERhdGUsIFNwZWNpZXMsIFN0cmFpbiwgSDJPMikgJT4lIAogIG11dGF0ZShyTSA9IHJbUHJpbWFyeSA9PSAiTW9jayJdLCBhc3IgPSByL3JNKSAlPiUKICBmaWx0ZXIoUHJpbWFyeSAhPSAiTW9jayIpICU+JSAKICByZW5hbWUoclAgPSAiciIsIHIgPSAick0iKSAlPiUgCiAgcmVsb2NhdGUoYyhyLCBhc3IpLCAuYWZ0ZXIgPSAiclAiKSAlPiUgCiAgdW5ncm91cCgpCgpkYXQuN2FzICU+JSBzZWxlY3QoLUdlbm90eXBlLCAtR3JvdXAsIC1EaWx1dGlvbnMsIC1Db3VudCwgLXNjYWxlZCkgJT4lIAogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMuZG91YmxlKSwgcm91bmQsIGRpZ2l0cyA9IDIpKQpgYGAKCmBgYHtyfQpkYXQuN2FzICU+JSAKICBncm91cF9ieShTZWNvbmRhcnksIFNwZWNpZXMpICU+JSAKICBzdW1tYXJpemUoCiAgICAjIHNtZWFuLmNsLmJvb3QgcmV0dXJucyBhIG5hbWVkIHZlY3Rvci4gdCgpICU+JSBhc190aWJibGUoKSB0dXJucyBpdAogICAgIyBpbnRvIGEgb25lLXJvdyB0aWJibGUsIHN0b3JlZCBhcyBhIGxpc3QgY29sdW1uLiB1bm5lc3QoKSB0aGVuIGZsYXR0ZW5zCiAgICAjIHRoZSBsaXN0LWNvbHVtbiBiYWNrIG91dCBpbnRvIHJlZ3VsYXIgY29sdW1ucwogICAgdGVzdCA9IEhtaXNjOjpzbWVhbi5jbC5ib290KEFTUl9TY29yZSkgJT4lIHQoKSAlPiUgYXNfdGliYmxlKCkKICApICU+JSAKICB1bm5lc3QodGVzdCkgJT4lIAogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIHJvdW5kLCBkaWdpdHMgPSAyKSkKYGBgCgpXaWxjb3hvbiBzaWduZWQtcmFuayB0ZXN0IGNvbXBhcmluZyByJyBhbmQgciAocGFpcmVkIGRhdGEpCmBgYHtyfQpkYXQuN2FzICU+JSAKICBzZWxlY3QoU3BlY2llcywgU2Vjb25kYXJ5LCByLCByUCkgJT4lIAogIG5lc3QoZGF0YSA9IGMociwgclApKSAlPiUgCiAgbXV0YXRlKAogICAgdGVzdCA9IG1hcChkYXRhLCB+IHdpbGNveC50ZXN0KC54JHJQLCAueCRyLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpLAogICAgdGlkaWVkID0gbWFwKHRlc3QsIHRpZHkpCiAgKSAlPiUgCiAgdW5uZXN0KHRpZGllZCkgJT4lIAogIHNlbGVjdChTcGVjaWVzLCBTZWNvbmRhcnksIFQgPSBzdGF0aXN0aWMsIHAudmFsdWUsIGFsdGVybmF0aXZlKSAlPiUgCiAgbXV0YXRlKHAuYm9uZiA9IHAuYWRqdXN0KHAudmFsdWUsIG1ldGhvZCA9ICJib25mIiksCiAgICAgICAgIHAuaG9sbSA9IHAuYWRqdXN0KHAudmFsdWUsIG1ldGhvZCA9ICJob2xtIiksCiAgICAgICAgIHAuaG9jaCA9IHAuYWRqdXN0KHAudmFsdWUsIG1ldGhvZCA9ICJob2NoIiksCiAgICAgICAgIGFjcm9zcyhzdGFydHNfd2l0aCgicC4iKSwgcm91bmQsIGRpZ2l0cyA9IDUpKQpgYGAKClBhaXJlZCB0LXRlc3RzIGNvbXBhcmluZyByJyBhbmQgcgpgYGB7cn0KZGF0LjdhcyAlPiUgCiAgc2VsZWN0KFNwZWNpZXMsIFNlY29uZGFyeSwgciwgclApICU+JSAKICBuZXN0KGRhdGEgPSBjKHIsIHJQKSkgJT4lIAogIG11dGF0ZSgKICAgIHRlc3QgPSBtYXAoZGF0YSwgfiB0LnRlc3QoLngkclAsIC54JHIsIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSksCiAgICB0aWRpZWQgPSBtYXAodGVzdCwgdGlkeSkKICApICU+JSAKICB1bm5lc3QodGlkaWVkKSAlPiUgCiAgc2VsZWN0KFNwZWNpZXMsIFNlY29uZGFyeSwgcC52YWx1ZSwgYWx0ZXJuYXRpdmUpICU+JSAKICBtdXRhdGUoUC5hZGogPSBwLmFkanVzdChwLnZhbHVlLCBtZXRob2QgPSAiQkgiKSwKICAgICAgICAgYWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLCByb3VuZCwgZGlnaXRzID0gMykpCmBgYAoKPiBJbiBjb25jbHVzaW9uLCB3ZSBmb3VuZCBzaWduaWZpY2FudCBBU1IgZWZmZWN0IGF0IDEyNSBuZy9tTCByYXBhbXljaW4gdHJlYXRtZW50IGluIF9DLiBnbGFicmF0YV8gdXNpbmcgZWl0aGVyIGEgV2lsY294b24gc2lnbmVkLXJhbmsgdGVzdCAobm9ucGFyYW1ldHJpYykgb3IgYSBwYWlyZWQgdCB0ZXN0LCBib3RoIHVzaW5nIGEgMC4wNSByZWplY3Rpb24gdGhyZWhvbGQuIFRoZSBzYW1lIHRlc3QgYXBwcm9hY2hlZCB0aGUgMC4wNSBzaWduaWZpY2FuY2UgdGhyZXNob2xkIGluIF9TLiBjZXJldmlzaWFlXwoKIyMgRmlnN18yOiBBU1IgaW4gU2NoOS0zRSBtdXRhbnQKXyoqR29hbCoqXwoKVGVzdCBpZiBTY2g5LTNFIG11dGFudCByZXN1bHRzIGluIHJlZHVjZWQgQVNSLgoKXyoqUmF0aW9uYWxlKipfCgpJdCBpcyBrbm93biBpbiBfUy4gY2VyZXZpc2lhZV8gdGhhdCBUT1JDMS1pbmhpYml0aW9uIGxlYWRzIHRvIHRoZSBkZXJlcHJlc3Npb24gb2YgTXNuMi80LW1lZGlhdGVkIHN0cmVzcyByZXNwb25zZSB2aWEgdGhlIFRPUkMxLVNjaDktUmltMTUgcGF0aHdheS4gU3BlY2lmaWNhbGx5LCBTY2g5IGlzIGEga2V5IHByb3hpbWFsIGVmZmVjdG9yIG9mIFRPUkMxLCB3aGljaCBwaG9zcGhvcnlsYXRlcyB0aGUgZm9ybWVyLiBQaG9zcGhvcnlsYXRlZCBTY2g5IHRoZW4gcGhvc3Bob3J5bGF0ZXMgUmltMTUsIGNhdXNpbmcgaXQgdG8gYmUgcmV0YWluZWQgaW4gdGhlIGN5dG9wbGFzbSBhbmQgdW5hYmxlIHRvIGFjdGl2YXRlIE1zbjIvNCBpbiB0aGUgbnVjbGV1cy4gSmlueWUgY3JlYXRlZCBhIHBob3NwaG9taW1ldGljIG11dGFudCBvZiBTY2g5IChha2EgU2NoOS0zRSkgdGhhdCBpcyBwcmVkaWN0ZWQgdG8gYmUgY29uc3RpdHV0aXZlbHkgYWN0aXZlIHdpdGggcmVzcGVjdCB0byBUT1JDMSBzaWduYWxpbmcuIFRoZXJlZm9yZSwgdGhpcyBtdXRhbnQgaXMgZXhwZWN0ZWQgdG8gYWx3YXlzIHJlcHJlc3MgdGhlIFJpbTE1LU1zbjQgZG93bnN0cmVhbSBlZmZlY3RvcnMgZXZlbiB3aGVuIFRPUkMxIGl0c2VsZiBpcyBpbmhpYml0ZWQuCgpfKipEYXRhKipfCgpTcGVjaWVzICAgICAgIEdlbm90eXBlICAgICAgICAgICAgIEgyTzIgIAotLS0tLS0tLSAgICAgIC0tLS0tLS0tLS0tLS0tLS0tLSAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCkMuIGdsYWJyYXRhICAgc2NoOTo6U0NIOS13dC1OYXQgICAgMCwgMjAsIDQwLCA2MCwgODAsIDEwMCBtTSAKQy4gZ2xhYnJhdGEgICBzY2g5OjpTQ0g5LTNFLU5hdCAgICAwLCAyMCwgNDAsIDYwLCA4MCwgMTAwIG1NCgpBU1IgZXhwZXJpbWVudHMgd2VyZSByZXBlYXRlZCBmb3VyIHRpbWVzIGZvciB0aGUgdHdvIHN0cmFpbnMgb24gZm91ciBjb25zZWN1dGl2ZSBkYXlzLCBmcm9tIDA1LzE0LTA1LzE3IG9mIDIwMjMuCgojIyMgUmVhZCBpbiBkYXRhClJlZm9ybWF0IEpZJ3MgZGF0YSBpbnRvIGEgdGlkeSBmb3JtYXQKYGBge3J9CnRtcCA8LSByZWFkX2NzdigiLi4vaW5wdXQvMjAyMzA1MTUtQ2dTQ0g5LTNFLWRhdGEtankuY3N2IiwgY29sX3R5cGVzID0gY29scygpLCBjb21tZW50ID0gIiMiKSAlPiUgCiAgbXV0YXRlKERhdGUgPSBnc3ViKCJkKFxcZFxcZCkoXFxkXFxkKShcXGRcXGQpIiwgIlxcMS9cXDIvXFwzIiwgRGF0ZSksCiAgICAgICAgIEgyTzIgPSBnc3ViKCJtTSIsICIgbU0iLCBIMk8yKSwKICAgICAgICAgTGVuXzEgPSByZWNvZGUoTGVuXzEsIGAyaHJgID0gIjIgaHIiLCBgNDVtaW5gID0gIjQ1IG1pbiIpLAogICAgICAgICBMZW5fMiA9IHJlY29kZShMZW5fMiwgYDJocmAgPSAiMiBociIpKSAlPiUgCiAgc2VsZWN0KC1gTU8vTU1fcGVyY2VudGAsIC1gUE8vUE1fcGVyY2VudGApCgojIGRhdGEgc2FuaXR5IGNoZWNrLCBxdWljayB2aWV3CnNhcHBseShzZWxlY3QodG1wLCBTcGVjaWVzLCBTdHJhaW4sIEdlbm90eXBlLCBMZW5fMSwgTGVuXzIsIEgyTzIpLCB1bmlxdWUpCgpkYXQuZjdiIDwtIHRtcCAlPiUgCiAgcGl2b3RfbG9uZ2VyKGMoQ291bnRfTU9fTU0sIENvdW50X1BPX1BNKSwgbmFtZXNfdG8gPSAiUHJpbWFyeSIsIHZhbHVlc190byA9ICJDb3VudCIpICU+JSAKICBtdXRhdGUoUHJpbWFyeSA9IGZjdF9yZWNvZGUoUHJpbWFyeSwgIk1vY2siID0gIkNvdW50X01PX01NIiwgIi1QaSIgPSAiQ291bnRfUE9fUE0iKSwKICAgICAgICAgR2Vub3R5cGUgPSBmY3RfcmVjb2RlKEdlbm90eXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYHNjaDk6OlNjaDktM0UtTkFUYCA9ICJzY2g5XzNFX05hdCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgc2NoOTo6U2NoOS1XVC1OQVRgID0gInNjaDlfTmF0X3d0IiksCiAgICAgICAgIHNjYWxlZCA9IENvdW50ICogRGlsdXRpb25zICogMWUtMykgJT4lIAogIGdyb3VwX2J5KERhdGUsIFN0cmFpbiwgR2Vub3R5cGUsIFByaW1hcnkpICU+JSAKICBtdXRhdGUociA9IG51bShzY2FsZWQgLyBzY2FsZWRbSDJPMiA9PSAiTW9jayJdLCBkaWdpdHMgPSAzKSkgJT4lIAogIHNlbGVjdChEYXRlLCBTcGVjaWVzLCBTdHJhaW4sIEdlbm90eXBlLCBQcmltYXJ5LCBIMk8yLCBEaWx1dGlvbnMsIENvdW50LCBzY2FsZWQsIHIpICU+JSAKICBhcnJhbmdlKERhdGUsIEdlbm90eXBlLCBQcmltYXJ5KQpgYGAKCldyaXRlIHRoZSB0YWJsZSB0byBhIGZpbGUgZm9yIGZ1dHVyZSByZWZlcmVuY2VzCmBgYHtyfQp3cml0ZV90c3YoZGF0LmY3YiwgZmlsZSA9ICIuLi9pbnB1dC8yMDIzMDUyMC1maWctNy1TY2g5LTNFLWRhdGEtaGIudHN2IikKYGBgCgojIyMgQ2FsaWJyYXRlIHNlY29uZGFyeSBzdHJlc3Mgc3RyZW5ndGgKSmlueWUgdGVzdGVkIGEgc2VyaWVzIG9mIEgyTzIgY29uY2VudHJhdGlvbnMgaW4gdGhpcyBleHBlcmltZW50LCBpLmUuLCAyMCwgNDAsIDYwLCA4MCBhbmQgMTAwIG1NLiBUaGUgZ29hbCBoZXJlIGlzIHRvIHZpc3VhbGl6ZSB0aGUgc3Vydml2YWwgcmF0ZXMgYmV0d2VlbiB0aGUgdHdvIGdlbm90eXBlcyBhbmQgZGVjaWRlIHdoaWNoIHBhaXIgdG8gdXNlIGZvciBBU1IgY29tcGFyaXNvbnMuCgpgYGB7cn0KZGF0LmY3YiAlPiUgCiAgZmlsdGVyKFByaW1hcnkgPT0gIk1vY2siLCBIMk8yICE9ICJNb2NrIikgJT4lIAogIG11dGF0ZShIMk8yID0gZ3N1YigiIG1NIiwgIiIsIEgyTzIpLAogICAgICAgICBIMk8yID0gZmFjdG9yKEgyTzIpICU+JSBmY3RfcmVvcmRlcihhcy5udW1lcmljKEgyTzIpKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IEgyTzIsIHkgPSByLCBncm91cCA9IEdlbm90eXBlKSkgKyAKICBnZW9tX2JhcihhZXMoZmlsbCA9IEdlbm90eXBlKSwgc3RhdCA9ICJzdW1tYXJ5IiwgZnVuID0gIm1lYW4iLAogICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC45KSkgKwogIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpLCBzaXplID0gMSwgY29sb3IgPSAiZ3JheTMwIikgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIsIGRpcmVjdGlvbiA9IC0xKSArCiAgeGxhYihicXVvdGUoSFsyXSpPWzJdfihtTSkpKSArIHlsYWIoIlN1cnZpdmFsIHJhdGUiKSArCiAgdGhlbWVfY293cGxvdCgpCmBgYAo+IFNvbWV3aGF0IHRvIG15IHN1cnByaXNlLCB0aGUgY29uc3RpdHV0aXZlbHkgYWN0aXZlIFNjaDktM0UgYWxsZWxlIHJlc3VsdGVkIGluIGJldHRlciBzdXJ2aXZhbCB3aXRob3V0IHByaW1hcnkgc3RyZXNzCgpGb3Igb3VyIHB1cnBvc2UsIGxldCdzIGNvbXBhcmUgNDAgbU0gYW5kIDYwIG1NIGZvciB0aGUgd3QgdG8gMTAwIG1NIGZvciB0aGUgU2NoOS0zRSBtdXRhbnQuCgpBIFdpbGNveG9uIHNpZ25lZC1yYW5rIHRlc3QgaXMgdXNlZCBoZXJlIHNpbmNlIHRoZSB0d28gZ3JvdXBzIGFyZSBkZXBlbmRlbnQgKD1ncm91cGVkKSBieSB0aGUgZGF5IG9mIHRoZSBleHBlcmltZW50LiBPbmUgcmVwbGljYXRlIHdhcyBydW4gcGVyIGRheS4gVXNpbmcgYSBwYWlyZWQtdGVzdCBlbnN1cmVzIHRoYXQgZGF5LXRvLWRheSB2YXJpYXRpb24gaXMgYWNjb3VudGVkIGZvci4KYGBge3J9CngxID0gZmlsdGVyKGRhdC5mN2IsIEdlbm90eXBlID09ICJzY2g5OjpTY2g5LVdULU5BVCIsIEgyTzIgPT0gIjQwIG1NIikgJT4lIHB1bGwocikgJT4lIGFzLmRvdWJsZSgpCngyID0gZmlsdGVyKGRhdC5mN2IsIEdlbm90eXBlID09ICJzY2g5OjpTY2g5LVdULU5BVCIsIEgyTzIgPT0gIjYwIG1NIikgJT4lIHB1bGwocikgJT4lIGFzLmRvdWJsZSgpCnkgPSBmaWx0ZXIoZGF0LmY3YiwgR2Vub3R5cGUgPT0gInNjaDk6OlNjaDktM0UtTkFUIiwgSDJPMiA9PSAiMTAwIG1NIikgJT4lIHB1bGwocikgJT4lIGFzLmRvdWJsZSgpCmNiaW5kKCJ3dCA0MG1NIiA9IHgxLCAid3QgNjBtTSIgPSB4MiwgIjNFIDEwMG1NIiA9IHkpCgpjYXQoIlxuIikKIyBXaWxjb3hvbiBzaWduZWQtcmFuayB0ZXN0cwpjYXQoIjx3dCA0MG1NPiB2cyA8d3QgNjBtTT4iKQp3aWxjb3gudGVzdCh4MSwgeDIsIHBhaXJlZCA9IFRSVUUpCmNhdCgiPHd0IDQwbU0+IHZzIDwzRSAxMDBtTT4iKQp3aWxjb3gudGVzdCh4MSwgeSwgcGFpcmVkID0gVFJVRSkKY2F0KCI8d3QgNjBtTT4gdnMgPDNFIDEwMG1NPiIpCndpbGNveC50ZXN0KHgyLCB5LCBwYWlyZWQgPSBUUlVFKQoKY2F0KCJcbiIpCiMgcGFpcmVkIHQtdGVzdApjYXQoIjx3dCA0MG1NPiB2cyA8d3QgODBtTT4iKQp0LnRlc3QoeDEsIHgyLCBwYWlyZWQgPSBUUlVFKQpjYXQoIjx3dCA0MG1NPiB2cyA8M0UgMTAwbU0+IikKdC50ZXN0KHgxLCB5LCBwYWlyZWQgPSBUUlVFKQpjYXQoIjx3dCA2MG1NPiB2cyA8M0UgMTAwbU0+IikKdC50ZXN0KHgyLCB5LCBwYWlyZWQgPSBUUlVFKQpgYGAKPiBGb3IgdGhlIHd0IHN0cmFpbiwgNDAgbU0gY2xlYXJseSByZXN1bHRlZCBpbiBiZXR0ZXIgc3Vydml2YWwgdGhhbiA2MCBtTSwgYXMgZXhwZWN0ZWQuCj4gV2hlbiBjb21wYXJpbmcgYmV0d2VlbiB3dCBhbmQgM0UgbXV0YW50LCA0MCBtTSBmb3Igd3QgYW5kIDEwMCBtTSBmb3IgM0UgaGF2ZSBtZWFuIHN1cnZpdmFsIHJhdGVzIHRoYXQgYXJlIGNsb3Nlci4gUGFpcmVkIHN0YXRpc3RpY2FsIHRlc3RzIHlpZWxkIFAtdmFsdWVzIGdyZWF0ZXIgdGhhbiAwLjEgZm9yIGJvdGggdGhlIDQwbU0gYW5kIDYwbU0gb2Ygd3QgY29tcGFyZWQgd2l0aCAxMDBtTSBmb3IgdGhlIDNFIG11dGFudC4KCiMjIyBFREE6IGRhdC10by1kYXkgdmFyaWF0aW9uCkZyb20gdGhlIHBsb3QgZm9yIHRoZSBiYXNhbCBzdXJ2aXZhbCByYXRlIGFib3ZlLCB0aGVyZSBhcHBlYXJzIHRvIGJlIGEgbG90IG9mIGRheS10by1kYXkgdmFyaWF0aW9uLiBIZXJlIHdlIHZpc3VhbGl6ZSB0aGlzIHZhcmlhdGlvbiBtb3JlIGNsZWFybHkKYGBge3J9CmRhdC5mN2IgJT4lIAogIGZpbHRlcihIMk8yICE9ICJNb2NrIikgJT4lIAogIG11dGF0ZShIMk8yID0gZ3N1YigiIG1NIiwgIiIsIEgyTzIpLAogICAgICAgICBIMk8yID0gZmFjdG9yKEgyTzIpICU+JSBmY3RfcmVvcmRlcihhcy5udW1lcmljKEgyTzIpKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IEgyTzIsIHkgPSByKSkgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IEdlbm90eXBlLCBzaGFwZSA9IERhdGUsIGdyb3VwID0gR2Vub3R5cGUpLCAKICAgICAgICAgICAgIHNpemUgPSAyLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKC41KSkgKyAKICB4bGFiKGJxdW90ZShIWzJdKk9bMl1+KG1NKSkpICsgeWxhYigiU3Vydml2YWwgcmF0ZSIpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJTZXQyIiwgZGlyZWN0aW9uID0gLTEpICsKICBmYWNldF93cmFwKH5QcmltYXJ5LCBucm93ID0gMikgKyB0aGVtZV9jb3dwbG90KCkgKwogIGJhY2tncm91bmRfZ3JpZChtYWpvciA9ICJ5IikKYGBgCgojIyMgQVNSLXNjb3JlIGNvbXBhcmlzb24KV2Ugd2lsbCBzdWJzZXQgdGhlIGRhdGEgdG8gaW5jbHVkZSB0aGUgNDAgbU0gYW5kIDYwIG1NIGZvciBXVCBhbmQgMTAwIG1NIGZvciAzRQpgYGB7cn0KZGF0LjdicCA8LSB1bmdyb3VwKGRhdC5mN2IpICU+JSAKICBmaWx0ZXIoSDJPMiAhPSAiTW9jayIpICU+JSAKICBtdXRhdGUoCiAgICBIMk8yID0gZ3N1YigiIG1NIiwgIiIsIEgyTzIpLAogICAgSDJPMiA9IGZhY3RvcihIMk8yKSAlPiUgZmN0X3Jlb3JkZXIoYXMubnVtZXJpYyhIMk8yKSksCiAgICBncm91cCA9IHBhc3RlKHN0cl9zdWIoR2Vub3R5cGUsIDEyLCAxMyksIEgyTzIsIHNlcCA9ICJfIikKICApICU+JSAKICBmaWx0ZXIoSDJPMiAhPSAiTW9jayIsIGdyb3VwICVpbiUgYygiM0VfMTAwIiwgIldUXzYwIiwgIldUXzQwIikpICU+JSAKICBzZWxlY3QoLURpbHV0aW9ucywgLUNvdW50LCAtU3BlY2llcykKCmRhdC43YnMgPC0gZGF0LjdicCAlPiUKICBncm91cF9ieShEYXRlLCBTdHJhaW4sIEdlbm90eXBlLCBIMk8yKSAlPiUgIyBmb3JtIGdyb3VwcyB0byBhcHBseSB0aGUgc2FtZSBNTy9NTQogIG11dGF0ZSgKICAgIHJNID0gcltQcmltYXJ5ID09ICJNb2NrIl0sICMgTU8vTU0gZm9yIGVhY2ggZ3JvdXAKICAgIEFTUl9TY29yZSA9IHIvck0KICApICU+JSB1bmdyb3VwKCkgJT4lCiAgcmVuYW1lKHJQID0gInIiLCByID0gInJNIikgJT4lIAogIGZpbHRlcihQcmltYXJ5ICE9ICJNb2NrIikgJT4lIAogIHJlbG9jYXRlKGMociwgQVNSX1Njb3JlKSwgLmFmdGVyID0gInJQIikKYGBgCgojIyMjIFBsb3QKTWFpbiBjb21wYXJpc29uIHdpbGwgYmUgYmV0d2VlbiB3dF80MCBhbmQgM0VfMTAwCmBgYHtyfQpkYXQuN2JwICU+JSAKICAjIG9ubHkgZXhhbWluZSB3dF80MCB2cyAzRV8xMDAKICBmaWx0ZXIoZ3JvdXAgIT0gIldUXzYwIikgJT4lIAogIGdncGxvdChhZXMoeCA9IFByaW1hcnksIHkgPSByKSkgKyBwLnN1cnZpdmFsWy0xXSArCiAgZ2VvbV9saW5lKGFlcyhncm91cCA9IERhdGUpLCBsaW5ldHlwZSA9IDIsIGxpbmV3aWR0aCA9IDAuMykgKyAKICBnZW9tX3BvaW50KHNoYXBlID0gMSwgc3Ryb2tlID0gMSwgc2l6ZSA9IDEpICsKICBmYWNldF93cmFwKH5HZW5vdHlwZSkgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC45KSkpCmdnc2F2ZSgiLi4vb3V0cHV0LzIwMjMwNTIwLVNjaDktM0UtdnMtd3QtQVNSLnBuZyIsIHdpZHRoID0gNC41LCBoZWlnaHQgPSAyLjIpCmBgYAogIAojIyMjIFN0YXRpc3RpY2FsIHRlc3QKClN1bW1hcnkgc3RhdGlzdGljcwpgYGB7cn0KZGF0LjdicyAlPiUgCiAgZ3JvdXBfYnkoR2Vub3R5cGUsIGdyb3VwKSAlPiUgCiAgc3VtbWFyaXplKAogICAgIyBzbWVhbi5jbC5ib290IHJldHVybnMgYSBuYW1lZCB2ZWN0b3IuIHQoKSAlPiUgYXNfdGliYmxlKCkgdHVybnMgaXQKICAgICMgaW50byBhIG9uZS1yb3cgdGliYmxlLCBzdG9yZWQgYXMgYSBsaXN0IGNvbHVtbi4gdW5uZXN0KCkgdGhlbiBmbGF0dGVucwogICAgIyB0aGUgbGlzdC1jb2x1bW4gYmFjayBvdXQgaW50byByZWd1bGFyIGNvbHVtbnMKICAgIHRlc3QgPSBIbWlzYzo6c21lYW4uY2wuYm9vdChhcy5kb3VibGUoQVNSX1Njb3JlKSkgJT4lIHQoKSAlPiUgYXNfdGliYmxlKCkKICApICU+JSAKICB1bm5lc3QodGVzdCkgJT4lIAogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIHJvdW5kLCBkaWdpdHMgPSAyKSkKYGBgCgpXaWxjb3hvbiBzaWduZWQtcmFuayB0ZXN0IGNvbXBhcmluZyByJyBhbmQgciAocGFpcmVkIGRhdGEpCmBgYHtyfQpkYXQuN2JzICU+JSAKICBzZWxlY3QoR2Vub3R5cGUsIGdyb3VwLCByLCByUCkgJT4lIAogIG5lc3QoZGF0YSA9IGMociwgclApKSAlPiUgCiAgbXV0YXRlKAogICAgdGVzdCA9IG1hcChkYXRhLCB+IHdpbGNveC50ZXN0KC54JHJQLCAueCRyLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJnIikpLAogICAgdGlkaWVkID0gbWFwKHRlc3QsIHRpZHkpCiAgKSAlPiUgCiAgdW5uZXN0KHRpZGllZCkgJT4lIAogIHNlbGVjdChHZW5vdHlwZSwgZ3JvdXAsIFQgPSBzdGF0aXN0aWMsIHAudmFsdWUsIGFsdGVybmF0aXZlKSAlPiUgCiAgbXV0YXRlKHAuYm9uZiA9IHAuYWRqdXN0KHAudmFsdWUsIG1ldGhvZCA9ICJib25mIiksCiAgICAgICAgIHAuaG9sbSA9IHAuYWRqdXN0KHAudmFsdWUsIG1ldGhvZCA9ICJob2xtIiksCiAgICAgICAgIHAuaG9jaCA9IHAuYWRqdXN0KHAudmFsdWUsIG1ldGhvZCA9ICJob2NoIiksCiAgICAgICAgIGFjcm9zcyhzdGFydHNfd2l0aCgicC4iKSwgcm91bmQsIGRpZ2l0cyA9IDUpKQpgYGAKClBhaXJlZCB0LXRlc3RzIGNvbXBhcmluZyByJyBhbmQgcgpgYGB7cn0KZGF0LjdicyAlPiUgCiAgI2ZpbHRlcihwcmltYXJ5ICE9ICIwTmkiKSAlPiUgCiAgc2VsZWN0KEdlbm90eXBlLCBncm91cCwgciwgclApICU+JSAKICBuZXN0KGRhdGEgPSBjKHIsIHJQKSkgJT4lIAogIG11dGF0ZSgKICAgIHRlc3QgPSBtYXAoZGF0YSwgfiB0LnRlc3QoLngkclAsIC54JHIsIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gImciKSksCiAgICB0aWRpZWQgPSBtYXAodGVzdCwgdGlkeSkKICApICU+JSAKICB1bm5lc3QodGlkaWVkKSAlPiUgCiAgc2VsZWN0KEdlbm90eXBlLCBncm91cCwgcC52YWx1ZSwgYWx0ZXJuYXRpdmUpICU+JSAKICBtdXRhdGUoUC5hZGogPSBwLmFkanVzdChwLnZhbHVlLCBtZXRob2QgPSAiQkgiKSwKICAgICAgICAgYWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLCByb3VuZCwgZGlnaXRzID0gMykpCmBgYAoKPiBJbiBjb25jbHVzaW9uLCB3ZSBmb3VuZCBzaWduaWZpY2FudCBBU1IgZWZmZWN0IGF0IDEyNSBuZy9tTCByYXBhbXljaW4gdHJlYXRtZW50IGluIF9DLiBnbGFicmF0YV8gdXNpbmcgZWl0aGVyIGEgV2lsY294b24gc2lnbmVkLXJhbmsgdGVzdCAobm9ucGFyYW1ldHJpYykgb3IgYSBwYWlyZWQgdCB0ZXN0LCBib3RoIHVzaW5nIGEgMC4wNSByZWplY3Rpb24gdGhyZWhvbGQuIFdlIGNvdWxkbid0IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIG9mIG5vIHN1cnZpdmFsIGRpZmZlcmVuY2UgYmV0d2VlbiByYXBhbXljaW4gdHJlYXRlZCB2cyB1bnRyZWF0ZWQgc2FtcGxlcyBmb3IgdGhlIDYyLjUgbmcvbUwgY29uY2VudHJhdGlvbiwgYW5kIGFsc28gbm90IGZvciB0aGUgaGlnaGVyIGRvc2UgaW4gX1MuIGNlcmV2aXNpYWVfCgoKIyMgUmVzcG9uc2UgdG8gcmV2aWV3ZXI6IEFTUiBpbiBtc2404oiGIGFuZCBza2434oiGIHZzIHd0Cl8qKkdvYWwqKl8KCkRldGVybWluZSBpZiB0cmFuc2NyaXB0aW9uYWwgZmFjdG9yIChURikgbXNuNCBhbmQgc2tuNyBjb250cmlidXRlIHRvIHRoZSBBU1IuCgpfKipSYXRpb25hbGUqKl8KCk1zbjQgYW5kIFNrbjcgYXJlIHN0cmVzcyByZXNwb25zaXZlIFRGcyByZWd1bGF0aW5nIHRoZSBDdGExLUdGUCBpbmR1Y3Rpb24gZHVyaW5nIHBob3NwaGF0ZSBzdGFydmF0aW9uLiBUaGUgcmV2aWV3ZXIgaXMgd29uZGVyaW5nIGlmIHRoZSBsb3NzIG9mIE1zbjQgb3IgU2tuNyBhZmZlY3QgdGhlIEFTUiBmb3IgSDJPMi4gVG8gYW5zd2VyIHRoaXMgcXVlc2lvbiwgSmlueWUgcGVyZm9ybWVkIHRoZSBDRlUgYXNzYXkgZm9yIEgyTzIgQVNSIHdpdGggYSBncmFkaWVudCBvZiBIMk8yIGNvbmNlbnRyYXRpb25zIGZvciB3dCwgbXNuNOKIhiBhbmQgc2tuN+KIhi4KCl8qKkRhdGEqKl8KClNwZWNpZXMgICAgICAgU3RyYWluICAgICAgICAgICBHZW5vdHlwZSAgICAgSDJPMiAgICAgICAgIAotLS0tLS0tLSAgICAgIC0tLS0tLS0tLS0tLS0gICAgLS0tLS0tLS0tLSAgIC0tLS0tLS0tLS0tLQpDLiBnbGFicmF0YSAgIHlIMDAxLCB5SDAwMiAgICAgd2lsZHR5cGUgICAgNjAsIDgwLCAxMDAgbU0gCkMuIGdsYWJyYXRhICAgeUgzOTYsIHlIMzk3ICAgICBfbXNuNOKIhl8gICAgIDIwLCA0MCwgNjAgbU0gCkMuIGdsYWJyYXRhICAgeUg0MjIsIHlINDIzICAgICBfc2tuN+KIhl8gICAgIDEwLCAyMCwgMzAsIDQwIG1NIAoKRml2ZSByZXBsaWNhdGVzIChhdCB0aHJlZSBbSDJPMl0pIGZvciB3dCBhbmQgX21zbjTiiIZfLCBmb3VyIHJlcGxpY2F0ZXMgKGF0IHRocmVlIFtIMk8yXSkgZm9yIF9za2434oiGXy4KCiMjIyBSZWFkIGFuZCBSZWZvcm1hdCBEYXRhCkppbnllIGhhcyByZWZvcm1hdHRlZCBoZXIgcmF3IGRhdGEgYW5kIHNhdmVkIHRoZSBvdXRwdXQgYXMgYSB0c3YuIFdlIHdpbGwgc2tpcCB0aGUgY29kZSBiZWxvdyBhbmQgZ28gc3RyYWlnaHQgdG8gdGhlIHJlZm9ybWF0dGVkIHZlcnNpb24uCgpgYGAKdG1wMSA8LSByZWFkX3RzdigiLi4vaW5wdXQvbXNuNG9yc2tuN19rb19BU1JfcmF3LnRzdiIsIGNvbF90eXBlcyA9IGNvbHMoKSwgY29tbWVudCA9ICIjIikgJT4lIAogIG11dGF0ZShEYXRlID0gZ3N1YigiKFxcZFxcZCkoXFxkXFxkKShcXGRcXGQpIiwgIlxcMS9cXDIvXFwzIiwgRGF0ZSkpICU+JSAKICBtdXRhdGUoSDJPMiA9IHJlY29kZShIMk8yLCAnTW9jaycgPSAnMG1NJykpICU+JSAKICBtdXRhdGUoSDJPMiA9IGdzdWIoIm1NIiwgIiBtTSIsIEgyTzIpKSAlPiUgCiAgc2VsZWN0KC1gTU8vTU1fcGVyY2VudGAsIC1gUE8vUE1fcGVyY2VudGApCgojIGRhdGEgc2FuaXR5IGNoZWNrLCBxdWljayB2aWV3CnNhcHBseShzZWxlY3QodG1wMSwgRGF0ZSwgU3BlY2llcywgU3RyYWluLCBHZW5vdHlwZSwgTGVuXzEsIExlbl8yLCBIMk8yKSwgdW5pcXVlKQoKZGF0LnNmIDwtIHRtcDEgJT4lIAogIHBpdm90X2xvbmdlcihjKENvdW50X01PX01NLCBDb3VudF9QT19QTSksIG5hbWVzX3RvID0gIlByaW1hcnkiLCB2YWx1ZXNfdG8gPSAiQ291bnQiKSAlPiUgCiAgbXV0YXRlKFByaW1hcnkgPSBmY3RfcmVjb2RlKFByaW1hcnksICJNb2NrIiA9ICJDb3VudF9NT19NTSIsICItUGkiID0gIkNvdW50X1BPX1BNIiksCiAgICAgICAgIHNjYWxlZCA9IENvdW50ICogRGlsdXRpb25zICogMWUtMykgJT4lIAogIGdyb3VwX2J5KERhdGUsIFN0cmFpbiwgR2Vub3R5cGUsIFByaW1hcnkpICU+JQogIG11dGF0ZShzY2FsZWRfTSA9IHNjYWxlZFtIMk8yID09ICIwIG1NIl0sCiAgICAgICAgIHIgPSBzY2FsZWQgLyBzY2FsZWRfTSkgJT4lCiAgdW5ncm91cCgpICU+JSAKICBzZWxlY3QoRGF0ZSwgU3BlY2llcywgU3RyYWluLCBHZW5vdHlwZSwgUHJpbWFyeSwgSDJPMiwgRGlsdXRpb25zLCAKICAgICAgICAgQ291bnQsIHNjYWxlZCwgc2NhbGVkX00sIHIpICU+JSAKICBhcnJhbmdlKERhdGUsIEdlbm90eXBlLCBQcmltYXJ5KQpgYGAKCmBgYAp3cml0ZV90c3YoZGF0LnNmLCBmaWxlID0gIi4uL2lucHV0LzIwMjMwOTEzLXNmLWRhdGEtSlkudHN2IikKYGBgCgpgYGB7cn0KZGF0LnNmIDwtIHJlYWRfdHN2KCIuLi9pbnB1dC8yMDIzMDkxMy1zZi1kYXRhLUpZLnRzdiIpCmBgYAoKIyMjIFBsb3QgKGFsbCBkYXRhKQpmaWx0ZXIgb3V0IHRoZSBza243zpQgNDBtTSB0cmVhdG1lbnQgZ3JvdXAsIGJlY2F1c2UgdGhlIFtIMk8yXSBpcyB0b28gaGlnaCBhY2NvcmRpbmcgdG8gdGhlIHNwb3R0aW5nIGFzc2F5IHJlc3VsdC4gCgpgYGB7cn0KZGF0LnNmcCA8LSBkYXQuc2YgJT4lIAogIGZpbHRlcihIMk8yICE9ICIwIG1NIiwgIShIMk8yID09ICI0MCBtTSIgJiBHZW5vdHlwZSA9PSAic2tuN86UIikpICU+JSAKICBtdXRhdGUoCiAgICBHZW5vdHlwZSA9IGZhY3RvcihHZW5vdHlwZSwgbGV2ZWxzID0gYygid3QiLCAibXNuNM6UIiwgInNrbjfOlCIpKSwKICAgIGdyb3VwID0gcGFzdGUoR2Vub3R5cGUsIGdzdWIoIiAiLCAiIiwgSDJPMiksIHNlcCA9ICJfIiksCiAgICBTZWNvbmRhcnkgPSAKICAgICAgZmFjdG9yKGdyb3VwLCAKICAgICAgICAgICAgIGxldmVscyA9IGMoInd0XzEwMG1NIiwgInd0XzgwbU0iLCAid3RfNjBtTSIsICJtc240zpRfNjBtTSIsIAogICAgICAgICAgICAgICAgICAgICAgICAibXNuNM6UXzQwbU0iLCAibXNuNM6UXzIwbU0iLAogICAgICAgICAgICAgICAgICAgICAgICAic2tuN86UXzMwbU0iLCAic2tuN86UXzIwbU0iLCAic2tuN86UXzEwbU0iKSwKICAgICAgICAgICAgIGxhYmVscyA9IGMoIkhpZ2giLCAiTWVkaXVtIiwgImxvdyIsICJIaWdoIiwgIk1lZGl1bSIsCiAgICAgICAgICAgICAgICAgICAgICAgICJsb3ciLCAiTWVkaXVtIiwgImxvdyIsICJib3R0b20iKSksCiAgICBQcmltYXJ5ID0gZmFjdG9yKFByaW1hcnksIGxldmVscyA9IGMoIk1vY2siLCAiLVBpIikpCiAgICAKICApCndpdGgoZGF0LnNmcCwgdGFibGUoRGF0ZSwgZ3JvdXApKQpgYGAKCmBgYHtyfQpkYXQuc2ZwICU+JQogIGdncGxvdChhZXMoeCA9IEgyTzIsIHkgPSByKSkgKyAjcC5zdXJ2aXZhbFstM10gKwogIGdlb21fcG9pbnQoYWVzKHNoYXBlID0gUHJpbWFyeSksIHN0cm9rZSA9IDEsIHNpemUgPSAyLCAKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gMC4yLCBkb2RnZS53aWR0aCA9IDAuOSkpICsKICBzdGF0X3N1bW1hcnkoYWVzKGdyb3VwID0gUHJpbWFyeSksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC45KSwKICAgICAgICAgICAgICAgZnVuID0gbWVhbiwgZnVuLm1heCA9IG1lYW4sIGZ1bi5taW4gPSBtZWFuLAogICAgICAgICAgICAgICBnZW9tID0gImNyb3NzYmFyIiwgY29sb3IgPSAicmVkIiwgd2lkdGggPSAwLjUpICsKICBmYWNldF93cmFwKH4gU2Vjb25kYXJ5ICsgR2Vub3R5cGUsIG5yb3cgPSAyLCBzY2FsZXMgPSAiZnJlZV94IiwgCiAgICAgICAgICAgICBsYWJlbGxlciA9IGxhYmVsbGVyKC5tdWx0aV9saW5lID0gRikpICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygiTW9jayIgPSAxLCAiLVBpIiA9IDE2KSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsKICB4bGFiKGJxdW90ZShIWzJdKk9bMl1+KG1NKSkpICsgeWxhYigiJSBzdXJ2aXZhbCIpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNCwgYmFzZV9saW5lX3NpemUgPSAxKSArCiAgcGFuZWxfYm9yZGVyKGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEpICsKICB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMC43KSwgZmFjZSA9IDMpLAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpCmBgYApQbG90IHRoZSBNZWRpdW0gZ3JvdXAgdG8gaW5jbHVkZSBpbiB0aGUgcmVzcG9uc2UgbGV0dGVyCmBgYHtyfQpkYXQuc2ZwICU+JQogIGZpbHRlcihTZWNvbmRhcnkgPT0gIk1lZGl1bSIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBIMk8yLCB5ID0gcikpICsgI3Auc3Vydml2YWxbLTNdICsKICBnZW9tX3BvaW50KGFlcyhzaGFwZSA9IFByaW1hcnkpLCBzdHJva2UgPSAxLCBzaXplID0gMiwgCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IDAuMiwgZG9kZ2Uud2lkdGggPSAwLjkpKSArCiAgc3RhdF9zdW1tYXJ5KGFlcyhncm91cCA9IFByaW1hcnkpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuOSksCiAgICAgICAgICAgICAgIGZ1biA9IG1lYW4sIGZ1bi5tYXggPSBtZWFuLCBmdW4ubWluID0gbWVhbiwKICAgICAgICAgICAgICAgZ2VvbSA9ICJjcm9zc2JhciIsIGNvbG9yID0gInJlZCIsIHdpZHRoID0gMC41KSArCiAgZmFjZXRfd3JhcCh+IEdlbm90eXBlLCBucm93ID0gMSwgc2NhbGVzID0gImZyZWVfeCIpICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygiTW9jayIgPSAxLCAiLVBpIiA9IDE2KSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsKICB4bGFiKGJxdW90ZShIWzJdKk9bMl1+KG1NKSkpICsgeWxhYigiJSBzdXJ2aXZhbCIpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNCwgYmFzZV9saW5lX3NpemUgPSAxKSArCiAgcGFuZWxfYm9yZGVyKGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEpICsKICB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMSksIGZhY2UgPSAzKSwKICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKQpnZ3NhdmUoIi4uL291dHB1dC8yMDIzMDkxMy1tc240LXNrbjctQVNSLnBuZyIsIHdpZHRoID0gNSwgaGVpZ2h0ID0gMykKYGBgCgojIyMgQmFzYWwgc3Vydml2YWwgcmF0ZXMKClN0YXRpc3RpY2FsIHRlc3QgZm9yIGRpZmZlcmVuY2VzIGluIGJhc2FsIHN1cnZpdmFsIGJldHdlZW4gZ2Vub3R5cGVzLiBJIGZpcnN0IGFwcGxpZWQgdGhlIEtydXNrYWwtV2FsbGlzIHRlc3QsIHdoaWNoIGlzIGFuIGV4dGVuc2lvbiBvZiB0aGUgTWFubi1XaGl0bmV5J3MgVSB0ZXN0IGZvciBtdWx0aXBsZSBncm91cHMgYW5kIGlzIGVxdWl2YWxlbnQgdG8gQU5PVkEgYnV0IGFwcGxpZWQgb24gcmFua3MuIEkgdXNlZCB0aGlzIHRlc3QgdG8gZGV0ZXJtaW5lIGlmIHRoZXJlIGlzIGV2aWRlbmNlIGZvciBkaWZmZXJlbmNlcyBpbiB0aGUgYmFzYWwgc3Vydml2YWwgcmF0ZXMgYW1vbmcgdGhlIGZvdXIgZ3JvdXBzICgyIGdlbm90eXBlcyB4IDIgW0gyTzJdKS4KCmBgYHtyfQp0bXAgPC0gZGF0LnNmcCAlPiUgZmlsdGVyKFNlY29uZGFyeSA9PSAiTWVkaXVtIiwgUHJpbWFyeSA9PSAiTW9jayIpCnRtcCAlPiUgZ3JvdXBfYnkoZ3JvdXApICU+JSAKICBzdW1tYXJpemUoCiAgICB0ZXN0ID0gSG1pc2M6OnNtZWFuLmNsLm5vcm1hbChyKSAlPiUgdCgpICU+JSBhc190aWJibGUoKQogICkgJT4lIAogIHVubmVzdCh0ZXN0KSAlPiUgCiAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5kb3VibGUpLCByb3VuZCwgZGlnaXRzID0gMykpCmtydXNrYWwudGVzdChyIH4gZ3JvdXAsIGRhdGEgPSB0bXApCmBgYAo+IFRoZXJlIGFyZSBubyBzaWduaWZpY2FuY2UgZGlmZmVyZW5jZXMgaW4gdGhlIGJhc2FsIHN1cnZpdmFsIHJhdGUgaW4gdGhlIE1lZGl1bSBncm91cCBhY3Jvc3MgZ2Vub3R5cGVzCgojIyMgU3RhdGlzdGljYWwgdGVzdCBmb3IgQVNSCkNvbXBhcmluZyB0aGUgQVNSIGVmZmVjdCBpbiBza243zpQsIG1zbjTiiIYgYW5kIHdpbGQgdHlwZSB1c2luZyBLcnVza2FsLVdhbGxpcyBSYW5rIFN1bSB0ZXN0LgpgYGB7cn0KdG1wIDwtIGRhdC5zZnAgJT4lIAogIGZpbHRlcihTZWNvbmRhcnkgPT0gIk1lZGl1bSIpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhEYXRlLCBTdHJhaW4sIEdlbm90eXBlKSwgbmFtZXNfZnJvbSA9IFByaW1hcnksIHZhbHVlc19mcm9tID0gcikgJT4lIAogIG11dGF0ZShBU1IgPSBgLVBpYC9Nb2NrKSAlPiUgCiAgYXJyYW5nZShHZW5vdHlwZSkKCnRtcCAlPiUgZ3JvdXBfYnkoR2Vub3R5cGUpICU+JSAKICBzdW1tYXJpemUoQVNSX3Njb3JlID0gcGFzdGUocm91bmQoYXMubnVtZXJpYyhBU1IpLDEpLCBjb2xsYXBzZSA9ICIsICIpLCAKICAgICAgICAgICAgbWVhbiA9IG1lYW4oQVNSKSwgc2QgPSBzZChBU1IpKQoKa3J1c2thbC50ZXN0KGFzLm51bWVyaWMoQVNSKSB+IEdlbm90eXBlLCBkYXRhID0gdG1wKQpwYWlyd2lzZS53aWxjb3gudGVzdCh4ID0gYXMubnVtZXJpYyh0bXAkQVNSKSwgZyA9IHRtcCRHZW5vdHlwZSwgcGFpcmVkID0gRkFMU0UsIHAuYWRqdXN0Lm1ldGhvZCA9ICJob2xtIikKYGBgCiAKPiBUaGVyZSBpcyBubyBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIEFTUiBhbW9uZyB0aGUgdGhyZWUgZ2Vub3R5cGVz